Part 0 - Topic introduction
People always use a lot of personal pronouns to avoid repeating someone’s names time and time again. Different people may use different personal pronouns for different weight in different situation to demonstrate different meanings and emotions. What about the situations in presidents’ Inaugural Speeches?
Part 1 - Packages preparaion
packages.used=c("RColorBrewer","qdap","ggplot2","reshape2","syuzhet","tm","qdap","reshape2","gridExtra","ggplot2","wordcloud","dplyr","tidytext")
# check packages that need to be installed.
packages.needed=setdiff(packages.used,
intersect(installed.packages()[,1],
packages.used))
# install additional packages
if(length(packages.needed)>0){
install.packages(packages.needed, dependencies = TRUE)
}
require(devtools,quietly = T)
install_github('recharts', 'taiyun')
Username parameter is deprecated. Please use taiyun/rechartsSkipping install of 'recharts' from a github remote, the SHA1 (9afee29c) has not changed since last install.
Use `force = TRUE` to force installation
# library packages
library("RColorBrewer",quietly = T)
library("qdap",quietly = T)
This data.table install has not detected OpenMP support. It will work but slower in single threaded mode.
载入程辑包:‘qdap’
The following object is masked from ‘package:base’:
Filter
library("ggplot2",quietly = T)
程辑包‘ggplot2’是用R版本3.3.2 来建造的
载入程辑包:‘ggplot2’
The following object is masked from ‘package:qdapRegex’:
%+%
library("reshape2",quietly = T)
library("syuzhet",quietly = T)
library("tm",quietly = T)
载入程辑包:‘NLP’
The following object is masked from ‘package:ggplot2’:
annotate
The following object is masked from ‘package:qdap’:
ngrams
载入程辑包:‘tm’
The following objects are masked from ‘package:qdap’:
as.DocumentTermMatrix, as.TermDocumentMatrix
library("qdap",quietly = T)
library("reshape2",quietly = T)
library("gridExtra",quietly = T)
library("ggplot2",quietly = T)
library("wordcloud",quietly = T)
library("dplyr",quietly = T)
载入程辑包:‘dplyr’
The following object is masked from ‘package:gridExtra’:
combine
The following object is masked from ‘package:qdap’:
%>%
The following object is masked from ‘package:qdapTools’:
id
The following objects are masked from ‘package:qdapRegex’:
escape, explain
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library("tidytext",quietly = T)
library("recharts",quietly = T)
载入程辑包:‘recharts’
The following object is masked from ‘package:ggplot2’:
%+%
The following object is masked from ‘package:qdap’:
%&%
The following object is masked from ‘package:qdapRegex’:
%+%
#part of codes are in this R file.
source("../lib/customized_function.R")
Part 2 - Data cleaning
We count the word frequency for each speeches and make this data matrix on which our whole analysis would based.
inaug.list=read.csv("../data/InaugurationInfo.csv", stringsAsFactors = FALSE)
inaug.data=read.table("../data/InauguationDates.txt", stringsAsFactors = FALSE,blank.lines.skip=F,sep= "\t")
mat1<-NULL
for(i in seq(nrow(inaug.list))) {
filename <- paste0("../data/InauguralSpeeches/inaug",
inaug.list$File[i], "-",
inaug.list$Term[i], ".txt")
tx <- readLines(filename,warn=F)
if (i==58)
{
tx<-paste(tx, collapse = " ")
tx_words <- strsplit(tx, split = " ")[[1]]
}
else
tx_words <- strsplit(tx, split = " ")[[1]]
date_pattern2 <- "[a-zA-z]+"
tx_words2 <- grep(tx_words, pattern = date_pattern2, value=T)
tx_log <- grepl(tx_words2, pattern = date_pattern2)
matches <- gregexpr(pattern = date_pattern2, text = tx_words2[tx_log])
tx_words <- unlist(regmatches(tx_words2[tx_log], matches))
tx_words <- unlist(rm_stopwords(tx_words))
mat<-NULL
table<-table(tx_words)
word<-names(table)
n<-unname(table)
matname<-paste(inaug.list$File[i],inaug.list$Term[i])
mat<-cbind(rep(matname,nrow(n)),word,n)
mat1<-rbind(mat1,mat)
}
colnames(mat1)<-c("name","word","n")
matsort<-mat1[order(as.numeric(mat1[,3]),decreasing = T),]
head(matsort)
name word n
[1,] "WilliamHenryHarrison 1" "which" "107"
[2,] "WilliamHenryHarrison 1" "by" "103"
[3,] "JamesKPolk 1" "our" "101"
[4,] "CalvinCoolidge 1" "we" "88"
[5,] "WilliamHenryHarrison 1" "their" "81"
[6,] "WarrenGHarding 1" "we" "80"
Part 3 - Different president uses personal pronoun for different weight
We divide personal pronouns into 4 types,first person singular form,first person plural form,second person form and third person form.
By saying weight,we mean the times one using a certain personal pronoun divided by the total times he using all four types of pronouns.
#personal pronoun
first1<-c("I","me","mine","my")
first2<-c("we","our","ours","us")
second<-c("you","your","yours")
third<-c("he","she","it","him","her","his","hers","they","them","their")
personal<-list(first1,first2,second,third)
pp_mat<-matrix(nrow = nrow(inaug.list),ncol = 4)
for(i in seq(nrow(inaug.list))) {
test<-matsort[matsort[,"name"]==paste(inaug.list$File[i],inaug.list$Term[i]),"word"]
pp_mat[i,]<-find_personal_pronoun(test)
}
ppname<-NULL
for(i in seq(nrow(inaug.list))) {
ppname[i] <- paste(inaug.list$File[i], inaug.list$Term[i]) }
rownames(pp_mat)<-ppname
colnames(pp_mat)<-c("first1","first2","second","third")
head(pp_mat)
first1 first2 second third
GeorgeWashington 1 0.2222222 0.3333333 0.1111111 0.3333333
GeorgeWashington 2 0.6666667 0.0000000 0.3333333 0.0000000
JohnAdams 1 0.2222222 0.4444444 0.1111111 0.2222222
ThomasJefferson 1 0.2222222 0.3333333 0.1111111 0.3333333
ThomasJefferson 2 0.2500000 0.3750000 0.1250000 0.2500000
JamesMadison 1 0.2857143 0.4285714 0.0000000 0.2857143
pp_mat1<-pp_mat
rownames(pp_mat1)<-seq(1789,2017,4)
pp_mat2<-melt(pp_mat1)
pp_mat3<-melt(pp_mat)
new1<-mat2mat(pp_mat)
a<-ggplot(data.frame(personal_pronoun=new1[,"type"],new1[,"name"],new1[,"prop"]), aes(x=factor(new1[,"name"], levels=unique(new1[,"name"])),y=new1[,"prop"], colour=personal_pronoun,group=personal_pronoun))+ geom_line(size=2) + theme(axis.text.x = element_blank()) + xlab("time with different presidents") + ylab("proportion")
pp_dat<-data.frame(year=pp_mat2$Var1,proportion=pp_mat2$value,personal_pronoun=pp_mat2$Var2)
b<-ggplot(pp_dat, aes(x = year, y = proportion, fill = personal_pronoun)) +
geom_area() +
scale_fill_brewer(palette = "Blues", breaks = rev(c("third","second","first2","first1")))
pp_dat<-data.frame(president=pp_mat3$Var1,proportion=pp_mat2$value,personal_pronoun=pp_mat2$Var2)
c<-ggplot(pp_dat,aes(president,proportion,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))+
scale_fill_brewer(palette = "Blues")+ theme(axis.text.x = element_blank()) + xlab("time with different presidents")
#grid.arrange(b,c,nrow=2)
Notice:The plot(and some following plots) are interactive by moving your mouse to a certain data point,details can be shown.
3.1 General Trend
x-axis:time (different presidents) y-axis:the weight of a certain kind of personal pronoun being used.
eArea(pp_mat1)
In general
- There is no obvious trend,just some fluctuations for second & third person using weight.
- There is a slightly decreasing for first person singular form using weight.
- There is a slightly increasing for first person plural form using weight.
It’s quite reasonable,since presidents come to realize that they should emphasize people’s rights and responsibilities to let people feel that they are being together,the interests of every citizens are closely related to destiny of the United States,rather than just talking about themselves.
3.2 Comparing between different terms
#different term
avg<-apply(pp_mat,2,mean)
list<-term_sep()
avg_term1<-apply(pp_mat[list[[1]],],2,mean)
avg_term2<-apply(pp_mat[list[[2]],],2,mean)
df1<-data.frame(avg,avg_term1,avg_term2)
dat<-t(df1)
mydat<-melt(dat)
#mydat
mydat<-data.frame(term = mydat$Var1,personal_pronoun = mydat$Var2,proportion=round(mydat$value,2))
ggplot(mydat,aes(term,proportion,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+theme(axis.ticks.length=unit(0.5,'cm'))+guides(fill=guide_legend(title=NULL))+
scale_fill_brewer(palette = "Blues")

eRadar(xtabs( proportion~ term+personal_pronoun, mydat))
From president’s term 1 to term 2,they tend to use more first person plural form than first person singular form.It’s also reasonable, since the president and the public become familiar to each other,so the president naturally take himself and the public as a whole group.
3.3 Comparing among different parties
#different party
new_inaug.list<-cbind(inaug.list,pp_mat)
first1<-tapply(new_inaug.list$first1,new_inaug.list$Party,mean)
first2<-tapply(new_inaug.list$first2,new_inaug.list$Party,mean)
second<-tapply(new_inaug.list$second,new_inaug.list$Party,mean)
third<-tapply(new_inaug.list$third,new_inaug.list$Party,mean)
#head(new_inaug.list)
#aggregate(new_inaug.list,)
dat<-rbind(unname(first1),unname(first2),unname(second),unname(third))
colnames(dat)<-names(first1)
rownames(dat)<-c("first1","first2","second","third")
mydat<-melt(dat)
mydat<-data.frame(personal_pronoun = mydat$Var1, party = mydat$Var2,proportion=round(mydat$value,2))
ggplot(mydat,aes(party,proportion,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+theme(axis.ticks.length=unit(0.5,'cm'))+guides(fill=guide_legend(title=NULL))+
scale_fill_brewer(palette = "Blues")+ theme(axis.text.x = element_text(angle = 15, hjust = 0.5, vjust = 0.5))

eRadar(xtabs( proportion~ party+personal_pronoun, mydat))
As the plot shown,Whig used first person singular form and third person most frequently,used first person plural form as well as second person at least frequency.While federalist is almost the opposite.
Part 4 - Analysis on each kind of personal pronoun’s CRAZY FAN
data1<-pp_mat[order(pp_mat[,1],decreasing = T),][1:10,]
data2<-pp_mat[order(pp_mat[,2],decreasing = T),][1:10,]
data3<-pp_mat[order(pp_mat[,3],decreasing = T),][1:10,]
data4<-pp_mat[order(pp_mat[,4],decreasing = T),][1:10,]
new1<-mat2mat(data1)
new2<-mat2mat(data2)
new3<-mat2mat(data3)
new4<-mat2mat(data4)
new1<-data.frame(type=new1[,"type"],name=new1[,"name"],proportion=as.numeric(new1[,"prop"]))
new2<-data.frame(type=new2[,"type"],name=new2[,"name"],proportion=as.numeric(new2[,"prop"]))
new3<-data.frame(type=new3[,"type"],name=new3[,"name"],proportion=as.numeric(new3[,"prop"]))
new4<-data.frame(type=new4[,"type"],name=new4[,"name"],proportion=as.numeric(new4[,"prop"]))
inaug.list=read.csv("../data/InaugurationInfo.csv", stringsAsFactors = FALSE)
inaug.data=read.table("../data/InauguationDates.txt", stringsAsFactors = FALSE,blank.lines.skip=F,sep= "\t")
first1<-c("I","me","mine","my")
first2<-c("we","our","ours","us")
second<-c("you","your","yours")
third<-c("he","she","it","him","her","his","hers","they","them","their")
personal<-list(first1,first2,second,third)
speech.list=read.csv("../data/InaugurationInfo.csv", stringsAsFactors = FALSE)
speech.list$type=c(rep("inaug", nrow(speech.list)))
speech.list$fulltext=NA
sentence.list=NULL
4.1 Top ten using first person singular form
- x-axis:different presidents
- y-axis:the weight of a certain kind of personal pronoun being used.
eBar(new1, ~name, ~proportion, ~type)
test<-topic_wc(2,1)
dat<-data.frame(word=test[,"word"],freq=5*as.numeric(test[,"n"]))
#par(mfrow=c(1,2))
eWordcloud(dat[7:65,], namevar = ~word, datavar = ~freq,size = c(600, 600),title = "George Washington & first person singular",rotationRange = c(-1, 1))
test<-topic_wc(2,3)
dat<-data.frame(word=test[,"word"],freq=5*as.numeric(test[,"n"]))
eWordcloud(dat[2:32,], namevar = ~word, datavar = ~freq,size = c(600, 600),title = "George Washington & second person",rotationRange = c(-1, 1))
No.1 “first person singular user” is George Washington(term 2).The 67% personal pronoun George Washington used in his second person is first person singular form. He also used second person quite frequently at about 33%. Along with the word cloud,we can speculate in his speeches,no matter using first singular form or second form,he used words like “administration”,“chief”,it was shown that he took himself as a leader and wanted to express his power to public.
test<-matsort[matsort[,"name"] == "WilliamMcKinley 1",]
test1<-matsort[matsort[,"name"] == "WoodrowWilson 2",]
test2<-matsort[matsort[,"name"] == "JamesBuchanan 1",]
test<-rbind(test,test1,test2)
test<-test[order(as.numeric(test[,3]),decreasing = T),]
test<-test[17:2529,]
dat<-data.frame(word=test[,"word"],freq=test[,"n"])
#par(mfrow=c(1,2))
eWordcloud(dat, namevar = ~word, datavar = ~freq,size = c(600, 600),title = "WilliamMcKinley 1 & WoodrowWilson 2 & JamesBuchanan 1",rotationRange = c(-1, 1))
Except Washington,from No.2 William McKinley(term 1) to No.4 James Buchanan(term 1),they didn’t even use second person.Add their three’s speeches to make the wordcloud,we can hardly find the words demonstrating centralization of power, instead,there are words like “congress”,“fair”,“civil”,“life”,showing more gentle emotion.
4.2 Top ten using first person plural form
- x-axis:different presidents
- y-axis:the weight of a certain kind of personal pronoun being used.
eBar(new2, ~name, ~proportion, ~type)
test<-matsort[matsort[,"name"] == "FranklinDRoosevelt 3",]
test1<-matsort[matsort[,"name"] == "TheodoreRoosevelt 1",]
test2<-matsort[matsort[,"name"] == "AndrewJackson 1",]
test3<-matsort[matsort[,"name"] == "AbrahamLincoln 2",]
test4<-matsort[matsort[,"name"] == "WilliamMcKinley 2",]
test5<-matsort[matsort[,"name"] == "FranklinDRoosevelt 4",]
test<-rbind(test,test1,test2,test3,test4,test5)
test<-test[order(as.numeric(test[,3]),decreasing = T),]
test<-test[40:2638,]
dat<-data.frame(word=test[,"word"],freq=test[,"n"])
#par(mfrow=c(1,2))
eWordcloud(dat, namevar = ~word, datavar = ~freq,size = c(600, 600),title = "TOP 6 using first person plural form",rotationRange = c(-1, 1))
For presidents frequently using first person plural form, there exists similar phenomenon.From No.1 Franklin DRoosevelt(term 3) to No.6 Franklin DRoosevelt(term 4),they also make the speeches without using second person.Add their speeches to make the wordcloud,we find similar words showing gentle emotion.
4.3 Top ten using second person
- x-axis:different presidents
- y-axis:the weight of a certain kind of personal pronoun being used.
eBar(new3, ~name, ~proportion, ~type)
4.4 Top ten using third person
- x-axis:different presidents
- y-axis:the weight of a certain kind of personal pronoun being used.
eBar(new4, ~name, ~proportion, ~type)
4.5 Each personal pronoun’s “Fan Club” feature : positive? negative?
data(positive.words)
data(negative.words)
sentiment_analy<-function(words)
{
score<-NULL
# compare words to the dictionaries of positive & negative terms
positive.matches = match(words, positive.words)
negative.matches = match(words, negative.words)
# get the position of the matched term or NA
# we just want a TRUE/FALSE
positive_matches = !is.na(positive.matches)
negative_matches = !is.na(negative.matches)
score = sum(positive_matches) - sum(negative_matches)
return(score)
}
senti_vec<-NULL
for(i in seq(nrow(inaug.list))) {
test<-matsort[matsort[,"name"]==paste(inaug.list$File[i],inaug.list$Term[i]),"word"]
senti_vec[i]<-sentiment_analy(test)
}
svname<-NULL
for(i in seq(nrow(inaug.list))) {
svname[i] <- paste(inaug.list$File[i], inaug.list$Term[i]) }
#sentiment vs person
senti_mat<-cbind(ppname,senti_vec)
n1<-match(rownames(data1),ppname)
n2<-match(rownames(data2),ppname)
n3<-match(rownames(data3),ppname)
n4<-match(rownames(data4),ppname)
senti_mat2<-cbind(senti_mat[n1,2],rep("first1",10))
senti_mat2<-rbind( senti_mat2 , cbind(senti_mat[n2,2],rep("first2",10)) )
senti_mat2<-rbind( senti_mat2 , cbind(senti_mat[n3,2],rep("second",10)) )
senti_mat2<-rbind( senti_mat2 , cbind(senti_mat[n4,2],rep("third",10)) )
colnames(senti_mat2)<-c("sentimental_scores","personal_pron")
dat<-data.frame(senti_mat2)
p <- ggplot(dat, aes(personal_pron, as.numeric(sentimental_scores)))
p + geom_boxplot()

According to the plot, First person plural’s “Fan Club” tend to be more negative,while the third person form’s “Fan Club” seem to be more positive. But there is no obvious differences.
4.6 Each personal pronoun’s “Fan Club” feature : average of word using times?
#avg time vs person
avg_mat<-matrix(nrow = nrow(inaug.list),ncol = 2)
avg_mat[,1]<-ppname
for(i in seq(nrow(inaug.list))) {
test<-matsort[matsort[,"name"]==paste(inaug.list$File[i],inaug.list$Term[i]),]
avg_mat[i,2]<-sum(as.numeric(test[,3]))/nrow(test)
}
senti_mat3<-cbind(avg_mat[n1,2],rep("first1",10))
senti_mat3<-rbind( senti_mat3 , cbind(avg_mat[n2,2],rep("first2",10)) )
senti_mat3<-rbind( senti_mat3 , cbind(avg_mat[n3,2],rep("second",10)) )
senti_mat3<-rbind( senti_mat3 , cbind(avg_mat[n4,2],rep("third",10)) )
colnames(senti_mat3)<-c("word_avg_time","personal_pron")
dat<-data.frame(senti_mat3)
p <- ggplot(dat, aes(personal_pron, as.numeric(word_avg_time)))
p + geom_boxplot()

According to the plot, First person plural’s “Fan Club” tend to use the same words for less times,the median is about 12 times;while the third person form’s “Fan Club” using the same words for more times,the median is about 27 times.
Part 5 - What are they talking/feeling using personal pronoun ?
In this part,we mainly make two plots to compare.One of them is stacked bar plot,demonstrating the four proportions of four personal pronouns for each sentence in one speech.The second is an area plot,showing different emotions for each sentence in one speech.
Finding 1:first singular form always come with trust and anticipation.
- George Washington: There are 4 sentences in his speeches,with 1,2 and 4 using high frequency of first person singular pronoun,and the emotions of these sentences are mainly trust.
senten_mat2<-melt(senten_mat(2))
sen_dat<-data.frame(sentence.number=senten_mat2$Var1,times=senten_mat2$value,personal_pronoun=senten_mat2$Var2,2)
senti_mat<-round(count_emo(2)[,c(1,2,4,5,7,8)],2)
rownames(senti_mat)<-seq(1,nrow(senti_mat))
senti_mat2<-melt(senti_mat)
senti_dat<-data.frame(sentence_number=senti_mat2$Var1,score=senti_mat2$value,sentiment=senti_mat2$Var2)
#par(mfrow=c(1,2))
a1<-ggplot(sen_dat,aes(sentence.number,times,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))+ scale_fill_brewer(palette = "Blues")+ xlab("sentence number")
#b1<-ggplot(senti_dat, aes(x = sentence_number, y = score, fill = sentiment)) +
# geom_area()
# + scale_fill_brewer(palette = "RdBu", breaks = rev(c(factor(sentiment))))
#b1<-ggplot(senti_dat,aes(x = sentence_number, y = score, fill = sentiment))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))
#grid.arrange(a1,b1,nrow=2)
a1
senten_mat2<-melt(senten_mat(2))
sen_dat<-data.frame(sentence.number=senten_mat2$Var1,times=senten_mat2$value,personal_pronoun=senten_mat2$Var2,2)
senti_mat<-round(count_emo(2)[,c(1,2,4,5,7,8)],2)
rownames(senti_mat)<-seq(1,nrow(senti_mat))
senti_mat2<-melt(senti_mat)
senti_dat<-data.frame(sentence_number=senti_mat2$Var1,score=senti_mat2$value,sentiment=senti_mat2$Var2)
#par(mfrow=c(1,2))
a1<-ggplot(sen_dat,aes(sentence.number,times,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))+ scale_fill_brewer(palette = "Blues")+ xlab("sentence number")
#b1<-ggplot(senti_dat, aes(x = sentence_number, y = score, fill = sentiment)) +
# geom_area()
# + scale_fill_brewer(palette = "RdBu", breaks = rev(c(factor(sentiment))))
#b1<-ggplot(senti_dat,aes(x = sentence_number, y = score, fill = sentiment))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))
#grid.arrange(a1,b1,nrow=2)
a1

eArea(senti_mat)
#find topics
#test<-topic_wc(2,1)
#test<-test[7:65,]
#dat<-data.frame(word=test[,"word"],freq=test[,"n"])
#eWordcloud(dat, namevar = ~word, datavar = ~freq,size = c(600, 600),title = "George Washington & fist person singular",rotationRange = c(-1, 1))
[for the area plot]
x-axis:sentence number
y-axis:the weight of a certain kind of emotion being detected.
- William McKinley: The sentences using first person singular pronoun frequently also contains trust emotion.
senten_mat2<-melt(senten_mat(28))
sen_dat<-data.frame(sentence.number=senten_mat2$Var1,times=senten_mat2$value,personal_pronoun=senten_mat2$Var2,2)
senti_mat<-round(count_emo(28)[,c(1,2,4,5,7,8)],2)
rownames(senti_mat)<-seq(1,nrow(senti_mat))
senti_mat2<-melt(senti_mat)
senti_dat<-data.frame(sentence_number=senti_mat2$Var1,score=senti_mat2$value,sentiment=senti_mat2$Var2)
#par(mfrow=c(1,2))
a1<-ggplot(sen_dat,aes(sentence.number,times,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))+ scale_fill_brewer(palette = "Blues")+ xlab("sentence number")
#b1<-ggplot(senti_dat, aes(x = sentence_number, y = score, fill = sentiment)) +
# geom_area()
# + scale_fill_brewer(palette = "RdBu", breaks = rev(c(factor(sentiment))))
#b1<-ggplot(senti_dat,aes(x = sentence_number, y = score, fill = sentiment))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))
#grid.arrange(a1,b1,nrow=2)
a1

eArea(senti_mat)
#find_sen(28,134)
#find_sen(28,135)
#find_sen(28,136)
#find_sen(28,137)
#test<-topic_wc(28,1)[1:60,]
#test<-test[6:60,]
#dat<-data.frame(word=test[,"word"],freq=test[,"n"])
#eWordcloud(dat, namevar = ~word, datavar = ~freq,size = c(600, 600),title = "WilliamMcKinley & fist person singular",rotationRange = c(-1, 1))
Finding 2 :first plural form always convey positive emotions.
senten_mat2<-melt(senten_mat(45))
sen_dat<-data.frame(sentence.number=senten_mat2$Var1,times=senten_mat2$value,personal_pronoun=senten_mat2$Var2)
par(mfrow=c(4,1), mar=c(1,0,2,0), bty="n", xaxt="n", yaxt="n", font.main=1)
a2<-ggplot(sen_dat,aes(sentence.number,times,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))+
scale_fill_brewer(palette = "Blues")+ xlab("sentence number")
senti_mat3<-round(count_emo(45)[,c(1,2,4,5,7,8)],2)
rownames(senti_mat3)<-seq(1,nrow(senti_mat3))
senti_mat4<-melt(senti_mat3)
senti_dat2<-data.frame(sentence_number=senti_mat4$Var1,score=senti_mat4$value,sentiment=senti_mat4$Var2)
#b2<-ggplot(senti_dat2, aes(x = sentence_number, y = score, fill = sentiment)) +
# geom_area()
#b2<-ggplot(senti_dat2,aes(x = sentence_number, y = score, fill = sentiment))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))
a2
senten_mat2<-melt(senten_mat(45))
sen_dat<-data.frame(sentence.number=senten_mat2$Var1,times=senten_mat2$value,personal_pronoun=senten_mat2$Var2)
par(mfrow=c(4,1), mar=c(1,0,2,0), bty="n", xaxt="n", yaxt="n", font.main=1)
a2<-ggplot(sen_dat,aes(sentence.number,times,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))+
scale_fill_brewer(palette = "Blues")+ xlab("sentence number")
senti_mat3<-round(count_emo(45)[,c(1,2,4,5,7,8)],2)
rownames(senti_mat3)<-seq(1,nrow(senti_mat3))
senti_mat4<-melt(senti_mat3)
senti_dat2<-data.frame(sentence_number=senti_mat4$Var1,score=senti_mat4$value,sentiment=senti_mat4$Var2)
#b2<-ggplot(senti_dat2, aes(x = sentence_number, y = score, fill = sentiment)) +
# geom_area()
#b2<-ggplot(senti_dat2,aes(x = sentence_number, y = score, fill = sentiment))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))
a2

apply(senti_mat3,2,mean)
anger anticipation fear joy surprise trust
0.01402062 0.03164948 0.03309278 0.03288660 0.01072165 0.05123711
eArea(senti_mat3)
#test<-topic_wc(45,2)[1:60,]
#dat<-data.frame(word=test[,"word"],freq=test[,"n"])
#eWordcloud(dat, namevar = ~word, datavar = ~freq)
[for the area plot]
x-axis:sentence number
y-axis:the weight of a certain kind of emotion being detected.
senten_mat2<-melt(senten_mat(57))
sen_dat<-data.frame(sentence.number=senten_mat2$Var1,times=senten_mat2$value,personal_pronoun=senten_mat2$Var2,2)
senti_mat<-round(count_emo(57)[,c(1,2,4,5,7,8)],2)
rownames(senti_mat)<-seq(1,nrow(senti_mat))
senti_mat2<-melt(senti_mat)
senti_dat<-data.frame(sentence_number=senti_mat2$Var1,score=senti_mat2$value,sentiment=senti_mat2$Var2)
#par(mfrow=c(1,2))
a1<-ggplot(sen_dat,aes(sentence.number,times,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))+ scale_fill_brewer(palette = "Blues")+ xlab("sentence number")
#b1<-ggplot(senti_dat, aes(x = sentence_number, y = score, fill = sentiment)) +
# geom_area()
# + scale_fill_brewer(palette = "RdBu", breaks = rev(c(factor(sentiment))))
#b1<-ggplot(senti_dat,aes(x = sentence_number, y = score, fill = sentiment))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))
#grid.arrange(a1,b1,nrow=2)
a1

eArea(senti_mat)
#find_sen(28,134)
#find_sen(28,135)
#find_sen(28,136)
#find_sen(28,137)
apply(senti_mat,2,mean)
anger anticipation fear joy surprise trust
0.01561905 0.03638095 0.02866667 0.03800000 0.01390476 0.04952381
#test<-topic_wc(35,2)[1:60,]
#dat<-data.frame(word=test[,"word"],freq=test[,"n"])
#eWordcloud(dat, namevar = ~word, datavar = ~freq)
Finding 3 : Anger often begin with third person form.
senten_mat2<-melt(senten_mat(21))
sen_dat<-data.frame(sentence.number=senten_mat2$Var1,times=senten_mat2$value,personal_pronoun=senten_mat2$Var2)
a3<-ggplot(sen_dat,aes(sentence.number,times,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))+ scale_fill_brewer(palette = "Blues")+ xlab("sentence number")
senti_mat5<-round(count_emo(21)[,c(1,2,4,5,7,8)],2)
rownames(senti_mat5)<-seq(1,nrow(senti_mat5))
senti_mat6<-melt(senti_mat5)
senti_dat3<-data.frame(sentence_number=senti_mat6$Var1,score=senti_mat6$value,sentiment=senti_mat6$Var2)
b3<-ggplot(senti_dat3,aes(x = sentence_number, y = score, fill = sentiment))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))
#b3<-ggplot(senti_dat3, aes(x = sentence_number, y = score, fill = sentiment)) +
# geom_area()
a3

eArea(senti_mat5)
apply(senti_mat5,2,mean,na.rm=T)
anger anticipation fear joy surprise trust
0.01704082 0.04326531 0.03316327 0.04204082 0.01255102 0.08020408
#test<-topic_wc(57,2)[1:60,]
#dat<-data.frame(word=test[,"word"],freq=test[,"n"])
#eWordcloud(dat, namevar = ~word, datavar = ~freq)
[for the area plot]
x-axis:sentence number
y-axis:the weight of a certain kind of emotion being detected.
senten_mat2<-melt(senten_mat(43))
sen_dat<-data.frame(sentence.number=senten_mat2$Var1,times=senten_mat2$value,personal_pronoun=senten_mat2$Var2)
a3<-ggplot(sen_dat,aes(sentence.number,times,fill=personal_pronoun))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))+ scale_fill_brewer(palette = "Blues")+ xlab("sentence number")
senti_mat5<-round(count_emo(43)[,c(1,2,4,5,7,8)],2)
rownames(senti_mat5)<-seq(1,nrow(senti_mat5))
senti_mat6<-melt(senti_mat5)
senti_dat3<-data.frame(sentence_number=senti_mat6$Var1,score=senti_mat6$value,sentiment=senti_mat6$Var2)
b3<-ggplot(senti_dat3,aes(x = sentence_number, y = score, fill = sentiment))+geom_bar(stat="identity",position="stack")+ggtitle("")+guides(fill=guide_legend(title=NULL))
#b3<-ggplot(senti_dat3, aes(x = sentence_number, y = score, fill = sentiment)) +
# geom_area()
a3

eArea(senti_mat5)
apply(senti_mat5,2,mean,na.rm=T)
anger anticipation fear joy surprise trust
0.01704082 0.04326531 0.03316327 0.04204082 0.01255102 0.08020408
#test<-topic_wc(57,2)[1:60,]
#dat<-data.frame(word=test[,"word"],freq=test[,"n"])
#eWordcloud(dat, namevar = ~word, datavar = ~freq)
Part 6 - Next step
Collect more data for other formal speeches to gain more convincing analysis.
Smooth the emotion function to make it more clear.
LS0tCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KPGRpdiBpZD0iaGVhZGVyIj4KPGgxIGNsYXNzPSJ0aXRsZSI+PGI+PGZvbnQgZmFjZT0iVGltZXMgTmV3IFJvbWFuIj5UaGUgdXNlIG9mIHBlcnNvbmFsIHByb25vdW4gaW4gSW5hdWd1cmFsIFNwZWVjaGVzPC9mb250PjwvYj48L2gxPgo8aDQgY2xhc3M9ImF1dGhvciI+PGVtPjxmb250IGZhY2U9IlRpbWVzIE5ldyBSb21hbiI+WWl0b25nIEh1PC9mb250PjwvZW0+PC9oND4KPGg0IGNsYXNzPSJkYXRlIj48ZW0+PGZvbnQgZmFjZT0iVGltZXMgTmV3IFJvbWFuIj5GZWJydWFyeSAzcmQuIDIwMTc8L2ZvbnQ+PC9lbT48L2g0Pgo8L2Rpdj4KPGRpdiBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXIiPiFbaW1hZ2VdKC4uL2ZpZ3MvcGVyc29uYWxwcm8uanBlZyk8L2Rpdj4KCjxoMz48Zm9udCBmYWNlPSJUaW1lcyBOZXcgUm9tYW4iPlBhcnQgMCAtIFRvcGljIGludHJvZHVjdGlvbjwvZm9udD48L2gzPgo8cD5QZW9wbGUgYWx3YXlzIHVzZSBhIGxvdCBvZiBwZXJzb25hbCBwcm9ub3VucyB0byBhdm9pZCByZXBlYXRpbmcgc29tZW9uZeKAmXMgbmFtZXMgdGltZSBhbmQgdGltZSBhZ2Fpbi4gRGlmZmVyZW50IHBlb3BsZSBtYXkgdXNlIGRpZmZlcmVudCBwZXJzb25hbCBwcm9ub3VucyBmb3IgZGlmZmVyZW50IHdlaWdodCBpbiBkaWZmZXJlbnQgc2l0dWF0aW9uIHRvIGRlbW9uc3RyYXRlIGRpZmZlcmVudCBtZWFuaW5ncyBhbmQgZW1vdGlvbnMuIFdoYXQgYWJvdXQgdGhlIHNpdHVhdGlvbnMgaW4gcHJlc2lkZW50cycgSW5hdWd1cmFsIFNwZWVjaGVzPzwvcD4KCgo8aDM+PGZvbnQgZmFjZT0iVGltZXMgTmV3IFJvbWFuIj5QYXJ0IDEgLSBQYWNrYWdlcyBwcmVwYXJhaW9uPC9mb250PjwvaDM+CgpgYGB7cixtZXNzYWdlPUYsd2FybmluZz1GfQpwYWNrYWdlcy51c2VkPWMoIlJDb2xvckJyZXdlciIsInFkYXAiLCJnZ3Bsb3QyIiwicmVzaGFwZTIiLCJzeXV6aGV0IiwidG0iLCJxZGFwIiwicmVzaGFwZTIiLCJncmlkRXh0cmEiLCJnZ3Bsb3QyIiwid29yZGNsb3VkIiwiZHBseXIiLCJ0aWR5dGV4dCIpCgojIGNoZWNrIHBhY2thZ2VzIHRoYXQgbmVlZCB0byBiZSBpbnN0YWxsZWQuCnBhY2thZ2VzLm5lZWRlZD1zZXRkaWZmKHBhY2thZ2VzLnVzZWQsIAogICAgICAgICAgICAgICAgICAgICAgICBpbnRlcnNlY3QoaW5zdGFsbGVkLnBhY2thZ2VzKClbLDFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2thZ2VzLnVzZWQpKQojIGluc3RhbGwgYWRkaXRpb25hbCBwYWNrYWdlcwppZihsZW5ndGgocGFja2FnZXMubmVlZGVkKT4wKXsKICBpbnN0YWxsLnBhY2thZ2VzKHBhY2thZ2VzLm5lZWRlZCwgZGVwZW5kZW5jaWVzID0gVFJVRSkKfQpyZXF1aXJlKGRldnRvb2xzLHF1aWV0bHkgPSBUKQppbnN0YWxsX2dpdGh1YigncmVjaGFydHMnLCAndGFpeXVuJykKCiMgbGlicmFyeSBwYWNrYWdlcwpsaWJyYXJ5KCJSQ29sb3JCcmV3ZXIiLHF1aWV0bHkgPSBUKQpsaWJyYXJ5KCJxZGFwIixxdWlldGx5ID0gVCkKbGlicmFyeSgiZ2dwbG90MiIscXVpZXRseSA9IFQpCmxpYnJhcnkoInJlc2hhcGUyIixxdWlldGx5ID0gVCkKbGlicmFyeSgic3l1emhldCIscXVpZXRseSA9IFQpCmxpYnJhcnkoInRtIixxdWlldGx5ID0gVCkKbGlicmFyeSgicWRhcCIscXVpZXRseSA9IFQpCmxpYnJhcnkoInJlc2hhcGUyIixxdWlldGx5ID0gVCkKbGlicmFyeSgiZ3JpZEV4dHJhIixxdWlldGx5ID0gVCkKbGlicmFyeSgiZ2dwbG90MiIscXVpZXRseSA9IFQpCmxpYnJhcnkoIndvcmRjbG91ZCIscXVpZXRseSA9IFQpCmxpYnJhcnkoImRwbHlyIixxdWlldGx5ID0gVCkKbGlicmFyeSgidGlkeXRleHQiLHF1aWV0bHkgPSBUKQpsaWJyYXJ5KCJyZWNoYXJ0cyIscXVpZXRseSA9IFQpCgojcGFydCBvZiBjb2RlcyBhcmUgaW4gdGhpcyBSIGZpbGUuCnNvdXJjZSgiLi4vbGliL2N1c3RvbWl6ZWRfZnVuY3Rpb24uUiIpCmBgYAoKCjxoMz48Zm9udCBmYWNlPSJUaW1lcyBOZXcgUm9tYW4iPlBhcnQgMiAtIERhdGEgY2xlYW5pbmc8L2ZvbnQ+PC9oMz4KCjxwPldlIGNvdW50IHRoZSB3b3JkIGZyZXF1ZW5jeSBmb3IgZWFjaCBzcGVlY2hlcyBhbmQgbWFrZSB0aGlzIGRhdGEgbWF0cml4IG9uIHdoaWNoIG91ciB3aG9sZSBhbmFseXNpcyB3b3VsZCBiYXNlZC48L3A+CgpgYGB7cix3YXJuaW5nPUZ9CmluYXVnLmxpc3Q9cmVhZC5jc3YoIi4uL2RhdGEvSW5hdWd1cmF0aW9uSW5mby5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmluYXVnLmRhdGE9cmVhZC50YWJsZSgiLi4vZGF0YS9JbmF1Z3VhdGlvbkRhdGVzLnR4dCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSxibGFuay5saW5lcy5za2lwPUYsc2VwPSAiXHQiKQptYXQxPC1OVUxMCgpmb3IoaSBpbiBzZXEobnJvdyhpbmF1Zy5saXN0KSkpIHsKZmlsZW5hbWUgPC0gcGFzdGUwKCIuLi9kYXRhL0luYXVndXJhbFNwZWVjaGVzL2luYXVnIiwgCiAgICAgICAgICAgICAgICAgICAgIGluYXVnLmxpc3QkRmlsZVtpXSwgIi0iLCAKICAgICAgICAgICAgICAgICAgICAgaW5hdWcubGlzdCRUZXJtW2ldLCAiLnR4dCIpCnR4IDwtIHJlYWRMaW5lcyhmaWxlbmFtZSx3YXJuPUYpCmlmIChpPT01OCkgCnsKICB0eDwtcGFzdGUodHgsIGNvbGxhcHNlID0gIiAiKQogIHR4X3dvcmRzIDwtIHN0cnNwbGl0KHR4LCBzcGxpdCA9ICIgIilbWzFdXQp9CmVsc2UKdHhfd29yZHMgPC0gc3Ryc3BsaXQodHgsIHNwbGl0ID0gIiAiKVtbMV1dCmRhdGVfcGF0dGVybjIgPC0gIlthLXpBLXpdKyIKdHhfd29yZHMyIDwtIGdyZXAodHhfd29yZHMsIHBhdHRlcm4gPSBkYXRlX3BhdHRlcm4yLCB2YWx1ZT1UKQp0eF9sb2cgPC0gZ3JlcGwodHhfd29yZHMyLCBwYXR0ZXJuID0gZGF0ZV9wYXR0ZXJuMikKbWF0Y2hlcyA8LSBncmVnZXhwcihwYXR0ZXJuID0gZGF0ZV9wYXR0ZXJuMiwgdGV4dCA9IHR4X3dvcmRzMlt0eF9sb2ddKQp0eF93b3JkcyA8LSB1bmxpc3QocmVnbWF0Y2hlcyh0eF93b3JkczJbdHhfbG9nXSwgbWF0Y2hlcykpCnR4X3dvcmRzIDwtIHVubGlzdChybV9zdG9wd29yZHModHhfd29yZHMpKQptYXQ8LU5VTEwKdGFibGU8LXRhYmxlKHR4X3dvcmRzKQp3b3JkPC1uYW1lcyh0YWJsZSkKbjwtdW5uYW1lKHRhYmxlKQptYXRuYW1lPC1wYXN0ZShpbmF1Zy5saXN0JEZpbGVbaV0saW5hdWcubGlzdCRUZXJtW2ldKQptYXQ8LWNiaW5kKHJlcChtYXRuYW1lLG5yb3cobikpLHdvcmQsbikKbWF0MTwtcmJpbmQobWF0MSxtYXQpCn0KY29sbmFtZXMobWF0MSk8LWMoIm5hbWUiLCJ3b3JkIiwibiIpIAptYXRzb3J0PC1tYXQxW29yZGVyKGFzLm51bWVyaWMobWF0MVssM10pLGRlY3JlYXNpbmcgPSBUKSxdCmhlYWQobWF0c29ydCkKYGBgCgo8aDM+PGZvbnQgZmFjZT0iVGltZXMgTmV3IFJvbWFuIj5QYXJ0IDMgLSBEaWZmZXJlbnQgcHJlc2lkZW50IHVzZXMgcGVyc29uYWwgcHJvbm91biBmb3IgZGlmZmVyZW50IHdlaWdodDwvZm9udD48L2gzPgoKPHA+V2UgZGl2aWRlIHBlcnNvbmFsIHByb25vdW5zIGludG8gNCB0eXBlcyxmaXJzdCBwZXJzb24gc2luZ3VsYXIgZm9ybSxmaXJzdCBwZXJzb24gcGx1cmFsIGZvcm0sc2Vjb25kIHBlcnNvbiBmb3JtIGFuZCB0aGlyZCBwZXJzb24gZm9ybS48L3A+CjxwPkJ5IHNheWluZyB3ZWlnaHQsd2UgbWVhbiB0aGUgdGltZXMgb25lIHVzaW5nIGEgY2VydGFpbiBwZXJzb25hbCBwcm9ub3VuIGRpdmlkZWQgYnkgdGhlIHRvdGFsIHRpbWVzIGhlIHVzaW5nIGFsbCBmb3VyIHR5cGVzIG9mIHByb25vdW5zLjwvcD4KCjxkaXYgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyIj4hW2ltYWdlXSguLi9maWdzL3BlcnNvbmFsdHlwZS5qcGVnKTwvZGl2PgoKYGBge3Isd2FybmluZz1GfQojcGVyc29uYWwgcHJvbm91bgoKZmlyc3QxPC1jKCJJIiwibWUiLCJtaW5lIiwibXkiKQpmaXJzdDI8LWMoIndlIiwib3VyIiwib3VycyIsInVzIikKc2Vjb25kPC1jKCJ5b3UiLCJ5b3VyIiwieW91cnMiKQp0aGlyZDwtYygiaGUiLCJzaGUiLCJpdCIsImhpbSIsImhlciIsImhpcyIsImhlcnMiLCJ0aGV5IiwidGhlbSIsInRoZWlyIikKcGVyc29uYWw8LWxpc3QoZmlyc3QxLGZpcnN0MixzZWNvbmQsdGhpcmQpCgpwcF9tYXQ8LW1hdHJpeChucm93ID0gbnJvdyhpbmF1Zy5saXN0KSxuY29sID0gNCkKZm9yKGkgaW4gc2VxKG5yb3coaW5hdWcubGlzdCkpKSB7CiAgdGVzdDwtbWF0c29ydFttYXRzb3J0WywibmFtZSJdPT1wYXN0ZShpbmF1Zy5saXN0JEZpbGVbaV0saW5hdWcubGlzdCRUZXJtW2ldKSwid29yZCJdCiAgcHBfbWF0W2ksXTwtZmluZF9wZXJzb25hbF9wcm9ub3VuKHRlc3QpCn0KcHBuYW1lPC1OVUxMCmZvcihpIGluIHNlcShucm93KGluYXVnLmxpc3QpKSkgewpwcG5hbWVbaV0gPC0gcGFzdGUoaW5hdWcubGlzdCRGaWxlW2ldLCBpbmF1Zy5saXN0JFRlcm1baV0pIH0Kcm93bmFtZXMocHBfbWF0KTwtcHBuYW1lCmNvbG5hbWVzKHBwX21hdCk8LWMoImZpcnN0MSIsImZpcnN0MiIsInNlY29uZCIsInRoaXJkIikKaGVhZChwcF9tYXQpCmBgYAoKYGBge3J9CnBwX21hdDE8LXBwX21hdApyb3duYW1lcyhwcF9tYXQxKTwtc2VxKDE3ODksMjAxNyw0KQpwcF9tYXQyPC1tZWx0KHBwX21hdDEpCnBwX21hdDM8LW1lbHQocHBfbWF0KQoKbmV3MTwtbWF0Mm1hdChwcF9tYXQpCmE8LWdncGxvdChkYXRhLmZyYW1lKHBlcnNvbmFsX3Byb25vdW49bmV3MVssInR5cGUiXSxuZXcxWywibmFtZSJdLG5ldzFbLCJwcm9wIl0pLCBhZXMoeD1mYWN0b3IobmV3MVssIm5hbWUiXSwgbGV2ZWxzPXVuaXF1ZShuZXcxWywibmFtZSJdKSkseT1uZXcxWywicHJvcCJdLCBjb2xvdXI9cGVyc29uYWxfcHJvbm91bixncm91cD1wZXJzb25hbF9wcm9ub3VuKSkrIGdlb21fbGluZShzaXplPTIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpICsgeGxhYigidGltZSB3aXRoIGRpZmZlcmVudCBwcmVzaWRlbnRzIikgKyB5bGFiKCJwcm9wb3J0aW9uIikgCgpwcF9kYXQ8LWRhdGEuZnJhbWUoeWVhcj1wcF9tYXQyJFZhcjEscHJvcG9ydGlvbj1wcF9tYXQyJHZhbHVlLHBlcnNvbmFsX3Byb25vdW49cHBfbWF0MiRWYXIyKQpiPC1nZ3Bsb3QocHBfZGF0LCBhZXMoeCA9IHllYXIsIHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gcGVyc29uYWxfcHJvbm91bikpICsKICBnZW9tX2FyZWEoKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJCbHVlcyIsIGJyZWFrcyA9IHJldihjKCJ0aGlyZCIsInNlY29uZCIsImZpcnN0MiIsImZpcnN0MSIpKSkKCnBwX2RhdDwtZGF0YS5mcmFtZShwcmVzaWRlbnQ9cHBfbWF0MyRWYXIxLHByb3BvcnRpb249cHBfbWF0MiR2YWx1ZSxwZXJzb25hbF9wcm9ub3VuPXBwX21hdDIkVmFyMikKYzwtZ2dwbG90KHBwX2RhdCxhZXMocHJlc2lkZW50LHByb3BvcnRpb24sZmlsbD1wZXJzb25hbF9wcm9ub3VuKSkrZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpK2dndGl0bGUoIiIpK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT1OVUxMKSkrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJCbHVlcyIpKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyB4bGFiKCJ0aW1lIHdpdGggZGlmZmVyZW50IHByZXNpZGVudHMiKQojZ3JpZC5hcnJhbmdlKGIsYyxucm93PTIpCmBgYAoKPHA+Tm90aWNlOlRoZSBwbG90KGFuZCBzb21lIGZvbGxvd2luZyBwbG90cykgYXJlIGludGVyYWN0aXZlIGJ5IG1vdmluZyB5b3VyIG1vdXNlIHRvIGEgY2VydGFpbiBkYXRhIHBvaW50LGRldGFpbHMgY2FuIGJlIHNob3duLjwvcD4KCjxoND4zLjEgR2VuZXJhbCBUcmVuZDwvaDQ+Cgp4LWF4aXM6dGltZSAoZGlmZmVyZW50IHByZXNpZGVudHMpCnktYXhpczp0aGUgd2VpZ2h0IG9mIGEgY2VydGFpbiBraW5kIG9mIHBlcnNvbmFsIHByb25vdW4gYmVpbmcgdXNlZC4KCmBgYHtyfQplQXJlYShwcF9tYXQxKQpgYGAKPHA+SW4gZ2VuZXJhbDwvcD4KKyBUaGVyZSBpcyBubyBvYnZpb3VzIHRyZW5kLGp1c3Qgc29tZSBmbHVjdHVhdGlvbnMgZm9yIHNlY29uZCAmIHRoaXJkIHBlcnNvbiB1c2luZyB3ZWlnaHQuCisgVGhlcmUgaXMgYSBzbGlnaHRseSBkZWNyZWFzaW5nIGZvciBmaXJzdCBwZXJzb24gc2luZ3VsYXIgZm9ybSB1c2luZyB3ZWlnaHQuCisgVGhlcmUgaXMgYSBzbGlnaHRseSBpbmNyZWFzaW5nIGZvciBmaXJzdCBwZXJzb24gcGx1cmFsIGZvcm0gdXNpbmcgd2VpZ2h0LgoKPHA+SXQncyBxdWl0ZSByZWFzb25hYmxlLHNpbmNlIHByZXNpZGVudHMgY29tZSB0byByZWFsaXplIHRoYXQgdGhleSBzaG91bGQgZW1waGFzaXplIHBlb3BsZSdzIHJpZ2h0cyBhbmQgcmVzcG9uc2liaWxpdGllcyB0byBsZXQgcGVvcGxlIGZlZWwgdGhhdCB0aGV5IGFyZSBiZWluZyB0b2dldGhlcix0aGUgaW50ZXJlc3RzIG9mIGV2ZXJ5IGNpdGl6ZW5zIGFyZSBjbG9zZWx5IHJlbGF0ZWQgdG8gZGVzdGlueSBvZiB0aGUgVW5pdGVkIFN0YXRlcyxyYXRoZXIgdGhhbiBqdXN0IHRhbGtpbmcgYWJvdXQgdGhlbXNlbHZlcy48L3A+CgoKPGg0PjMuMiBDb21wYXJpbmcgYmV0d2VlbiBkaWZmZXJlbnQgdGVybXM8L2g0PgoKCmBgYHtyLHdhcm5pbmc9Rn0KI2RpZmZlcmVudCB0ZXJtIAphdmc8LWFwcGx5KHBwX21hdCwyLG1lYW4pCmxpc3Q8LXRlcm1fc2VwKCkKYXZnX3Rlcm0xPC1hcHBseShwcF9tYXRbbGlzdFtbMV1dLF0sMixtZWFuKQphdmdfdGVybTI8LWFwcGx5KHBwX21hdFtsaXN0W1syXV0sXSwyLG1lYW4pCmRmMTwtZGF0YS5mcmFtZShhdmcsYXZnX3Rlcm0xLGF2Z190ZXJtMikKZGF0PC10KGRmMSkKbXlkYXQ8LW1lbHQoZGF0KQojbXlkYXQKbXlkYXQ8LWRhdGEuZnJhbWUodGVybSA9IG15ZGF0JFZhcjEscGVyc29uYWxfcHJvbm91biA9IG15ZGF0JFZhcjIscHJvcG9ydGlvbj1yb3VuZChteWRhdCR2YWx1ZSwyKSkKZ2dwbG90KG15ZGF0LGFlcyh0ZXJtLHByb3BvcnRpb24sZmlsbD1wZXJzb25hbF9wcm9ub3VuKSkrZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpK2dndGl0bGUoIiIpK3RoZW1lKGF4aXMudGlja3MubGVuZ3RoPXVuaXQoMC41LCdjbScpKStndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9TlVMTCkpKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiQmx1ZXMiKQplUmFkYXIoeHRhYnMoIHByb3BvcnRpb25+IHRlcm0rcGVyc29uYWxfcHJvbm91biwgbXlkYXQpKQpgYGAKPHA+RnJvbSBwcmVzaWRlbnQncyB0ZXJtIDEgdG8gdGVybSAyLHRoZXkgdGVuZCB0byB1c2UgbW9yZSBmaXJzdCBwZXJzb24gcGx1cmFsIGZvcm0gdGhhbiBmaXJzdCBwZXJzb24gc2luZ3VsYXIgZm9ybS5JdCdzIGFsc28gcmVhc29uYWJsZSwgc2luY2UgdGhlIHByZXNpZGVudCBhbmQgdGhlIHB1YmxpYyBiZWNvbWUgZmFtaWxpYXIgdG8gZWFjaCBvdGhlcixzbyB0aGUgcHJlc2lkZW50IG5hdHVyYWxseSB0YWtlIGhpbXNlbGYgYW5kIHRoZSBwdWJsaWMgYXMgYSB3aG9sZSBncm91cC48L3A+CgoKPGg0PjMuMyBDb21wYXJpbmcgYW1vbmcgZGlmZmVyZW50IHBhcnRpZXM8L2g0PgoKCmBgYHtyLHdhcm5pbmc9Rn0KI2RpZmZlcmVudCBwYXJ0eQpuZXdfaW5hdWcubGlzdDwtY2JpbmQoaW5hdWcubGlzdCxwcF9tYXQpCmZpcnN0MTwtdGFwcGx5KG5ld19pbmF1Zy5saXN0JGZpcnN0MSxuZXdfaW5hdWcubGlzdCRQYXJ0eSxtZWFuKQpmaXJzdDI8LXRhcHBseShuZXdfaW5hdWcubGlzdCRmaXJzdDIsbmV3X2luYXVnLmxpc3QkUGFydHksbWVhbikKc2Vjb25kPC10YXBwbHkobmV3X2luYXVnLmxpc3Qkc2Vjb25kLG5ld19pbmF1Zy5saXN0JFBhcnR5LG1lYW4pCnRoaXJkPC10YXBwbHkobmV3X2luYXVnLmxpc3QkdGhpcmQsbmV3X2luYXVnLmxpc3QkUGFydHksbWVhbikKI2hlYWQobmV3X2luYXVnLmxpc3QpCiNhZ2dyZWdhdGUobmV3X2luYXVnLmxpc3QsKQpkYXQ8LXJiaW5kKHVubmFtZShmaXJzdDEpLHVubmFtZShmaXJzdDIpLHVubmFtZShzZWNvbmQpLHVubmFtZSh0aGlyZCkpCmNvbG5hbWVzKGRhdCk8LW5hbWVzKGZpcnN0MSkKcm93bmFtZXMoZGF0KTwtYygiZmlyc3QxIiwiZmlyc3QyIiwic2Vjb25kIiwidGhpcmQiKQpteWRhdDwtbWVsdChkYXQpCm15ZGF0PC1kYXRhLmZyYW1lKHBlcnNvbmFsX3Byb25vdW4gPSBteWRhdCRWYXIxLCBwYXJ0eSA9IG15ZGF0JFZhcjIscHJvcG9ydGlvbj1yb3VuZChteWRhdCR2YWx1ZSwyKSkKZ2dwbG90KG15ZGF0LGFlcyhwYXJ0eSxwcm9wb3J0aW9uLGZpbGw9cGVyc29uYWxfcHJvbm91bikpK2dlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj0ic3RhY2siKStnZ3RpdGxlKCIiKSt0aGVtZShheGlzLnRpY2tzLmxlbmd0aD11bml0KDAuNSwnY20nKSkrZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPU5VTEwpKSsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkJsdWVzIikrIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMTUsIGhqdXN0ID0gMC41LCB2anVzdCA9IDAuNSkpCmVSYWRhcih4dGFicyggcHJvcG9ydGlvbn4gcGFydHkrcGVyc29uYWxfcHJvbm91biwgbXlkYXQpKQpgYGAKPHA+QXMgdGhlIHBsb3Qgc2hvd24sV2hpZyB1c2VkIGZpcnN0IHBlcnNvbiBzaW5ndWxhciBmb3JtIGFuZCB0aGlyZCBwZXJzb24gbW9zdCBmcmVxdWVudGx5LHVzZWQgZmlyc3QgcGVyc29uIHBsdXJhbCBmb3JtIGFzIHdlbGwgYXMgc2Vjb25kIHBlcnNvbiBhdCBsZWFzdCBmcmVxdWVuY3kuV2hpbGUgZmVkZXJhbGlzdCBpcyBhbG1vc3QgdGhlIG9wcG9zaXRlLjwvcD4KCgo8aDM+PGZvbnQgZmFjZT0iVGltZXMgTmV3IFJvbWFuIj5QYXJ0IDQgLSBBbmFseXNpcyBvbiBlYWNoIGtpbmQgb2YgcGVyc29uYWwgcHJvbm91bidzIENSQVpZIEZBTjwvZm9udD48L2gzPgpgYGB7cix3YXJuaW5nPUZ9CmRhdGExPC1wcF9tYXRbb3JkZXIocHBfbWF0WywxXSxkZWNyZWFzaW5nID0gVCksXVsxOjEwLF0KZGF0YTI8LXBwX21hdFtvcmRlcihwcF9tYXRbLDJdLGRlY3JlYXNpbmcgPSBUKSxdWzE6MTAsXQpkYXRhMzwtcHBfbWF0W29yZGVyKHBwX21hdFssM10sZGVjcmVhc2luZyA9IFQpLF1bMToxMCxdCmRhdGE0PC1wcF9tYXRbb3JkZXIocHBfbWF0Wyw0XSxkZWNyZWFzaW5nID0gVCksXVsxOjEwLF0KbmV3MTwtbWF0Mm1hdChkYXRhMSkKbmV3MjwtbWF0Mm1hdChkYXRhMikKbmV3MzwtbWF0Mm1hdChkYXRhMykKbmV3NDwtbWF0Mm1hdChkYXRhNCkKbmV3MTwtZGF0YS5mcmFtZSh0eXBlPW5ldzFbLCJ0eXBlIl0sbmFtZT1uZXcxWywibmFtZSJdLHByb3BvcnRpb249YXMubnVtZXJpYyhuZXcxWywicHJvcCJdKSkKbmV3MjwtZGF0YS5mcmFtZSh0eXBlPW5ldzJbLCJ0eXBlIl0sbmFtZT1uZXcyWywibmFtZSJdLHByb3BvcnRpb249YXMubnVtZXJpYyhuZXcyWywicHJvcCJdKSkKbmV3MzwtZGF0YS5mcmFtZSh0eXBlPW5ldzNbLCJ0eXBlIl0sbmFtZT1uZXczWywibmFtZSJdLHByb3BvcnRpb249YXMubnVtZXJpYyhuZXczWywicHJvcCJdKSkKbmV3NDwtZGF0YS5mcmFtZSh0eXBlPW5ldzRbLCJ0eXBlIl0sbmFtZT1uZXc0WywibmFtZSJdLHByb3BvcnRpb249YXMubnVtZXJpYyhuZXc0WywicHJvcCJdKSkKaW5hdWcubGlzdD1yZWFkLmNzdigiLi4vZGF0YS9JbmF1Z3VyYXRpb25JbmZvLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKaW5hdWcuZGF0YT1yZWFkLnRhYmxlKCIuLi9kYXRhL0luYXVndWF0aW9uRGF0ZXMudHh0Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLGJsYW5rLmxpbmVzLnNraXA9RixzZXA9ICJcdCIpCmZpcnN0MTwtYygiSSIsIm1lIiwibWluZSIsIm15IikKZmlyc3QyPC1jKCJ3ZSIsIm91ciIsIm91cnMiLCJ1cyIpCnNlY29uZDwtYygieW91IiwieW91ciIsInlvdXJzIikKdGhpcmQ8LWMoImhlIiwic2hlIiwiaXQiLCJoaW0iLCJoZXIiLCJoaXMiLCJoZXJzIiwidGhleSIsInRoZW0iLCJ0aGVpciIpCnBlcnNvbmFsPC1saXN0KGZpcnN0MSxmaXJzdDIsc2Vjb25kLHRoaXJkKQpzcGVlY2gubGlzdD1yZWFkLmNzdigiLi4vZGF0YS9JbmF1Z3VyYXRpb25JbmZvLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKc3BlZWNoLmxpc3QkdHlwZT1jKHJlcCgiaW5hdWciLCBucm93KHNwZWVjaC5saXN0KSkpCnNwZWVjaC5saXN0JGZ1bGx0ZXh0PU5BCnNlbnRlbmNlLmxpc3Q9TlVMTApgYGAKCgo8aDQ+NC4xIFRvcCB0ZW4gdXNpbmcgZmlyc3QgcGVyc29uIHNpbmd1bGFyIGZvcm08L2g0PgoKKyB4LWF4aXM6ZGlmZmVyZW50IHByZXNpZGVudHMKKyB5LWF4aXM6dGhlIHdlaWdodCBvZiBhIGNlcnRhaW4ga2luZCBvZiBwZXJzb25hbCBwcm9ub3VuIGJlaW5nIHVzZWQuCgpgYGB7cn0KZUJhcihuZXcxLCB+bmFtZSwgfnByb3BvcnRpb24sIH50eXBlKQpgYGAKCmBgYHtyfQp0ZXN0PC10b3BpY193YygyLDEpCmRhdDwtZGF0YS5mcmFtZSh3b3JkPXRlc3RbLCJ3b3JkIl0sZnJlcT01KmFzLm51bWVyaWModGVzdFssIm4iXSkpCiNwYXIobWZyb3c9YygxLDIpKQplV29yZGNsb3VkKGRhdFs3OjY1LF0sIG5hbWV2YXIgPSB+d29yZCwgZGF0YXZhciA9IH5mcmVxLHNpemUgPSBjKDYwMCwgNjAwKSx0aXRsZSA9ICJHZW9yZ2UgV2FzaGluZ3RvbiAmIGZpcnN0IHBlcnNvbiBzaW5ndWxhciIscm90YXRpb25SYW5nZSA9IGMoLTEsIDEpKQp0ZXN0PC10b3BpY193YygyLDMpCmRhdDwtZGF0YS5mcmFtZSh3b3JkPXRlc3RbLCJ3b3JkIl0sZnJlcT01KmFzLm51bWVyaWModGVzdFssIm4iXSkpCmVXb3JkY2xvdWQoZGF0WzI6MzIsXSwgbmFtZXZhciA9IH53b3JkLCBkYXRhdmFyID0gfmZyZXEsc2l6ZSA9IGMoNjAwLCA2MDApLHRpdGxlID0gIkdlb3JnZSBXYXNoaW5ndG9uICYgc2Vjb25kIHBlcnNvbiIscm90YXRpb25SYW5nZSA9IGMoLTEsIDEpKQpgYGAKPHA+Tm8uMSAiZmlyc3QgcGVyc29uIHNpbmd1bGFyIHVzZXIiIGlzIEdlb3JnZSBXYXNoaW5ndG9uKHRlcm0gMikuVGhlIDY3JSBwZXJzb25hbCBwcm9ub3VuIEdlb3JnZSBXYXNoaW5ndG9uIHVzZWQgaW4gaGlzIHNlY29uZCBwZXJzb24gaXMgZmlyc3QgcGVyc29uIHNpbmd1bGFyIGZvcm0uIEhlIGFsc28gdXNlZCBzZWNvbmQgcGVyc29uIHF1aXRlIGZyZXF1ZW50bHkgYXQgYWJvdXQgMzMlLiBBbG9uZyB3aXRoIHRoZSB3b3JkIGNsb3VkLHdlIGNhbiBzcGVjdWxhdGUgaW4gaGlzIHNwZWVjaGVzLG5vIG1hdHRlciB1c2luZyBmaXJzdCBzaW5ndWxhciBmb3JtIG9yIHNlY29uZCBmb3JtLGhlIHVzZWQgd29yZHMgbGlrZSAiYWRtaW5pc3RyYXRpb24iLCJjaGllZiIsaXQgd2FzIHNob3duIHRoYXQgaGUgdG9vayBoaW1zZWxmIGFzIGEgbGVhZGVyIGFuZCB3YW50ZWQgdG8gZXhwcmVzcyBoaXMgcG93ZXIgdG8gcHVibGljLjwvcD4KCmBgYHtyfQp0ZXN0PC1tYXRzb3J0W21hdHNvcnRbLCJuYW1lIl0gPT0gIldpbGxpYW1NY0tpbmxleSAxIixdCnRlc3QxPC1tYXRzb3J0W21hdHNvcnRbLCJuYW1lIl0gPT0gIldvb2Ryb3dXaWxzb24gMiIsXQp0ZXN0MjwtbWF0c29ydFttYXRzb3J0WywibmFtZSJdID09ICJKYW1lc0J1Y2hhbmFuIDEiLF0KdGVzdDwtcmJpbmQodGVzdCx0ZXN0MSx0ZXN0MikKdGVzdDwtdGVzdFtvcmRlcihhcy5udW1lcmljKHRlc3RbLDNdKSxkZWNyZWFzaW5nID0gVCksXQp0ZXN0PC10ZXN0WzE3OjI1MjksXQpkYXQ8LWRhdGEuZnJhbWUod29yZD10ZXN0Wywid29yZCJdLGZyZXE9dGVzdFssIm4iXSkKI3BhcihtZnJvdz1jKDEsMikpCmVXb3JkY2xvdWQoZGF0LCBuYW1ldmFyID0gfndvcmQsIGRhdGF2YXIgPSB+ZnJlcSxzaXplID0gYyg2MDAsIDYwMCksdGl0bGUgPSAiV2lsbGlhbU1jS2lubGV5IDEgJiBXb29kcm93V2lsc29uIDIgJiBKYW1lc0J1Y2hhbmFuIDEiLHJvdGF0aW9uUmFuZ2UgPSBjKC0xLCAxKSkKYGBgCjxwPkV4Y2VwdCBXYXNoaW5ndG9uLGZyb20gTm8uMiBXaWxsaWFtIE1jS2lubGV5KHRlcm0gMSkgdG8gTm8uNCBKYW1lcyBCdWNoYW5hbih0ZXJtIDEpLHRoZXkgZGlkbid0IGV2ZW4gdXNlIHNlY29uZCBwZXJzb24uQWRkIHRoZWlyIHRocmVlJ3Mgc3BlZWNoZXMgdG8gbWFrZSB0aGUgd29yZGNsb3VkLHdlIGNhbiBoYXJkbHkgZmluZCB0aGUgd29yZHMgZGVtb25zdHJhdGluZyBjZW50cmFsaXphdGlvbiBvZiBwb3dlciwgaW5zdGVhZCx0aGVyZSBhcmUgd29yZHMgbGlrZSAiY29uZ3Jlc3MiLCJmYWlyIiwiY2l2aWwiLCJsaWZlIixzaG93aW5nIG1vcmUgZ2VudGxlIGVtb3Rpb24uPC9wPgo8aDQ+NC4yIFRvcCB0ZW4gdXNpbmcgZmlyc3QgcGVyc29uIHBsdXJhbCBmb3JtPC9oND4KCisgeC1heGlzOmRpZmZlcmVudCBwcmVzaWRlbnRzCisgeS1heGlzOnRoZSB3ZWlnaHQgb2YgYSBjZXJ0YWluIGtpbmQgb2YgcGVyc29uYWwgcHJvbm91biBiZWluZyB1c2VkLgoKYGBge3J9CmVCYXIobmV3Miwgfm5hbWUsIH5wcm9wb3J0aW9uLCB+dHlwZSkKYGBgCgoKYGBge3J9CnRlc3Q8LW1hdHNvcnRbbWF0c29ydFssIm5hbWUiXSA9PSAiRnJhbmtsaW5EUm9vc2V2ZWx0IDMiLF0KdGVzdDE8LW1hdHNvcnRbbWF0c29ydFssIm5hbWUiXSA9PSAiVGhlb2RvcmVSb29zZXZlbHQgMSIsXQp0ZXN0MjwtbWF0c29ydFttYXRzb3J0WywibmFtZSJdID09ICJBbmRyZXdKYWNrc29uIDEiLF0KdGVzdDM8LW1hdHNvcnRbbWF0c29ydFssIm5hbWUiXSA9PSAiQWJyYWhhbUxpbmNvbG4gMiIsXQp0ZXN0NDwtbWF0c29ydFttYXRzb3J0WywibmFtZSJdID09ICJXaWxsaWFtTWNLaW5sZXkgMiIsXQp0ZXN0NTwtbWF0c29ydFttYXRzb3J0WywibmFtZSJdID09ICJGcmFua2xpbkRSb29zZXZlbHQgNCIsXQp0ZXN0PC1yYmluZCh0ZXN0LHRlc3QxLHRlc3QyLHRlc3QzLHRlc3Q0LHRlc3Q1KQp0ZXN0PC10ZXN0W29yZGVyKGFzLm51bWVyaWModGVzdFssM10pLGRlY3JlYXNpbmcgPSBUKSxdCnRlc3Q8LXRlc3RbNDA6MjYzOCxdCmRhdDwtZGF0YS5mcmFtZSh3b3JkPXRlc3RbLCJ3b3JkIl0sZnJlcT10ZXN0WywibiJdKQojcGFyKG1mcm93PWMoMSwyKSkKZVdvcmRjbG91ZChkYXQsIG5hbWV2YXIgPSB+d29yZCwgZGF0YXZhciA9IH5mcmVxLHNpemUgPSBjKDYwMCwgNjAwKSx0aXRsZSA9ICJUT1AgNiB1c2luZyBmaXJzdCBwZXJzb24gcGx1cmFsIGZvcm0iLHJvdGF0aW9uUmFuZ2UgPSBjKC0xLCAxKSkKYGBgCgo8cD5Gb3IgcHJlc2lkZW50cyBmcmVxdWVudGx5IHVzaW5nIGZpcnN0IHBlcnNvbiBwbHVyYWwgZm9ybSwgdGhlcmUgZXhpc3RzIHNpbWlsYXIgcGhlbm9tZW5vbi5Gcm9tIE5vLjEgRnJhbmtsaW4gRFJvb3NldmVsdCh0ZXJtIDMpIHRvIE5vLjYgRnJhbmtsaW4gRFJvb3NldmVsdCh0ZXJtIDQpLHRoZXkgYWxzbyBtYWtlIHRoZSBzcGVlY2hlcyB3aXRob3V0IHVzaW5nIHNlY29uZCBwZXJzb24uQWRkIHRoZWlyIHNwZWVjaGVzIHRvIG1ha2UgdGhlIHdvcmRjbG91ZCx3ZSBmaW5kIHNpbWlsYXIgd29yZHMgc2hvd2luZyBnZW50bGUgZW1vdGlvbi48L3A+Cgo8aDQ+NC4zIFRvcCB0ZW4gdXNpbmcgc2Vjb25kIHBlcnNvbjwvaDQ+CgorIHgtYXhpczpkaWZmZXJlbnQgcHJlc2lkZW50cworIHktYXhpczp0aGUgd2VpZ2h0IG9mIGEgY2VydGFpbiBraW5kIG9mIHBlcnNvbmFsIHByb25vdW4gYmVpbmcgdXNlZC4KCmBgYHtyfQplQmFyKG5ldzMsIH5uYW1lLCB+cHJvcG9ydGlvbiwgfnR5cGUpCmBgYAo8aDQ+NC40IFRvcCB0ZW4gdXNpbmcgdGhpcmQgcGVyc29uPC9oND4KCisgeC1heGlzOmRpZmZlcmVudCBwcmVzaWRlbnRzCisgeS1heGlzOnRoZSB3ZWlnaHQgb2YgYSBjZXJ0YWluIGtpbmQgb2YgcGVyc29uYWwgcHJvbm91biBiZWluZyB1c2VkLgoKYGBge3J9CmVCYXIobmV3NCwgfm5hbWUsIH5wcm9wb3J0aW9uLCB+dHlwZSkKYGBgCgo8aDQ+NC41IEVhY2ggcGVyc29uYWwgcHJvbm91bidzICJGYW4gQ2x1YiIgZmVhdHVyZSA6IHBvc2l0aXZlPyBuZWdhdGl2ZT8gPC9oND4KCmBgYHtyLHdhcm5pbmc9Rn0KZGF0YShwb3NpdGl2ZS53b3JkcykKZGF0YShuZWdhdGl2ZS53b3JkcykKc2VudGltZW50X2FuYWx5PC1mdW5jdGlvbih3b3JkcykKewogICAgICBzY29yZTwtTlVMTAogICAgICAjIGNvbXBhcmUgd29yZHMgdG8gdGhlIGRpY3Rpb25hcmllcyBvZiBwb3NpdGl2ZSAmIG5lZ2F0aXZlIHRlcm1zCiAgICAgIHBvc2l0aXZlLm1hdGNoZXMgPSBtYXRjaCh3b3JkcywgcG9zaXRpdmUud29yZHMpCiAgICAgIG5lZ2F0aXZlLm1hdGNoZXMgPSBtYXRjaCh3b3JkcywgbmVnYXRpdmUud29yZHMpCiAgICAgICMgZ2V0IHRoZSBwb3NpdGlvbiBvZiB0aGUgbWF0Y2hlZCB0ZXJtIG9yIE5BCiAgICAgICMgd2UganVzdCB3YW50IGEgVFJVRS9GQUxTRQogICAgICBwb3NpdGl2ZV9tYXRjaGVzID0gIWlzLm5hKHBvc2l0aXZlLm1hdGNoZXMpCiAgICAgIG5lZ2F0aXZlX21hdGNoZXMgPSAhaXMubmEobmVnYXRpdmUubWF0Y2hlcykKICAgICAgc2NvcmUgPSBzdW0ocG9zaXRpdmVfbWF0Y2hlcykgLSBzdW0obmVnYXRpdmVfbWF0Y2hlcykgCiAgICAgIHJldHVybihzY29yZSkKfQpzZW50aV92ZWM8LU5VTEwKZm9yKGkgaW4gc2VxKG5yb3coaW5hdWcubGlzdCkpKSB7CiAgdGVzdDwtbWF0c29ydFttYXRzb3J0WywibmFtZSJdPT1wYXN0ZShpbmF1Zy5saXN0JEZpbGVbaV0saW5hdWcubGlzdCRUZXJtW2ldKSwid29yZCJdCiAgc2VudGlfdmVjW2ldPC1zZW50aW1lbnRfYW5hbHkodGVzdCkKfQpzdm5hbWU8LU5VTEwKZm9yKGkgaW4gc2VxKG5yb3coaW5hdWcubGlzdCkpKSB7CnN2bmFtZVtpXSA8LSBwYXN0ZShpbmF1Zy5saXN0JEZpbGVbaV0sIGluYXVnLmxpc3QkVGVybVtpXSkgfQoKI3NlbnRpbWVudCB2cyBwZXJzb24Kc2VudGlfbWF0PC1jYmluZChwcG5hbWUsc2VudGlfdmVjKQpuMTwtbWF0Y2gocm93bmFtZXMoZGF0YTEpLHBwbmFtZSkKbjI8LW1hdGNoKHJvd25hbWVzKGRhdGEyKSxwcG5hbWUpCm4zPC1tYXRjaChyb3duYW1lcyhkYXRhMykscHBuYW1lKQpuNDwtbWF0Y2gocm93bmFtZXMoZGF0YTQpLHBwbmFtZSkKc2VudGlfbWF0MjwtY2JpbmQoc2VudGlfbWF0W24xLDJdLHJlcCgiZmlyc3QxIiwxMCkpCnNlbnRpX21hdDI8LXJiaW5kKCBzZW50aV9tYXQyICwgY2JpbmQoc2VudGlfbWF0W24yLDJdLHJlcCgiZmlyc3QyIiwxMCkpICkKc2VudGlfbWF0MjwtcmJpbmQoIHNlbnRpX21hdDIgLCBjYmluZChzZW50aV9tYXRbbjMsMl0scmVwKCJzZWNvbmQiLDEwKSkgKQpzZW50aV9tYXQyPC1yYmluZCggc2VudGlfbWF0MiAsIGNiaW5kKHNlbnRpX21hdFtuNCwyXSxyZXAoInRoaXJkIiwxMCkpICkKY29sbmFtZXMoc2VudGlfbWF0Mik8LWMoInNlbnRpbWVudGFsX3Njb3JlcyIsInBlcnNvbmFsX3Byb24iKQpkYXQ8LWRhdGEuZnJhbWUoc2VudGlfbWF0MikKcCA8LSBnZ3Bsb3QoZGF0LCBhZXMocGVyc29uYWxfcHJvbiwgYXMubnVtZXJpYyhzZW50aW1lbnRhbF9zY29yZXMpKSkKcCArIGdlb21fYm94cGxvdCgpCmBgYAoKPHA+QWNjb3JkaW5nIHRvIHRoZSBwbG90LCBGaXJzdCBwZXJzb24gcGx1cmFsJ3MgIkZhbiBDbHViIiB0ZW5kIHRvIGJlIG1vcmUgbmVnYXRpdmUsd2hpbGUgdGhlIHRoaXJkIHBlcnNvbiBmb3JtJ3MgIkZhbiBDbHViIiBzZWVtIHRvIGJlIG1vcmUgcG9zaXRpdmUuIEJ1dCB0aGVyZSBpcyBubyBvYnZpb3VzIGRpZmZlcmVuY2VzLjwvcD4KCjxoND40LjYgRWFjaCBwZXJzb25hbCBwcm9ub3VuJ3MgIkZhbiBDbHViIiBmZWF0dXJlIDogYXZlcmFnZSBvZiB3b3JkIHVzaW5nIHRpbWVzPyA8L2g0PgpgYGB7cix3YXJuaW5nPUZ9CiNhdmcgdGltZSB2cyBwZXJzb24KYXZnX21hdDwtbWF0cml4KG5yb3cgPSBucm93KGluYXVnLmxpc3QpLG5jb2wgPSAyKQphdmdfbWF0WywxXTwtcHBuYW1lCmZvcihpIGluIHNlcShucm93KGluYXVnLmxpc3QpKSkgewogIHRlc3Q8LW1hdHNvcnRbbWF0c29ydFssIm5hbWUiXT09cGFzdGUoaW5hdWcubGlzdCRGaWxlW2ldLGluYXVnLmxpc3QkVGVybVtpXSksXQogIGF2Z19tYXRbaSwyXTwtc3VtKGFzLm51bWVyaWModGVzdFssM10pKS9ucm93KHRlc3QpCn0Kc2VudGlfbWF0MzwtY2JpbmQoYXZnX21hdFtuMSwyXSxyZXAoImZpcnN0MSIsMTApKQpzZW50aV9tYXQzPC1yYmluZCggc2VudGlfbWF0MyAsIGNiaW5kKGF2Z19tYXRbbjIsMl0scmVwKCJmaXJzdDIiLDEwKSkgKQpzZW50aV9tYXQzPC1yYmluZCggc2VudGlfbWF0MyAsIGNiaW5kKGF2Z19tYXRbbjMsMl0scmVwKCJzZWNvbmQiLDEwKSkgKQpzZW50aV9tYXQzPC1yYmluZCggc2VudGlfbWF0MyAsIGNiaW5kKGF2Z19tYXRbbjQsMl0scmVwKCJ0aGlyZCIsMTApKSApCmNvbG5hbWVzKHNlbnRpX21hdDMpPC1jKCJ3b3JkX2F2Z190aW1lIiwicGVyc29uYWxfcHJvbiIpCmRhdDwtZGF0YS5mcmFtZShzZW50aV9tYXQzKQpwIDwtIGdncGxvdChkYXQsIGFlcyhwZXJzb25hbF9wcm9uLCBhcy5udW1lcmljKHdvcmRfYXZnX3RpbWUpKSkKcCArIGdlb21fYm94cGxvdCgpCmBgYAo8cD5BY2NvcmRpbmcgdG8gdGhlIHBsb3QsIEZpcnN0IHBlcnNvbiBwbHVyYWwncyAiRmFuIENsdWIiIHRlbmQgdG8gdXNlIHRoZSBzYW1lIHdvcmRzIGZvciBsZXNzIHRpbWVzLHRoZSBtZWRpYW4gaXMgYWJvdXQgMTIgdGltZXM7d2hpbGUgdGhlIHRoaXJkIHBlcnNvbiBmb3JtJ3MgIkZhbiBDbHViIiB1c2luZyB0aGUgc2FtZSB3b3JkcyBmb3IgbW9yZSB0aW1lcyx0aGUgbWVkaWFuIGlzIGFib3V0IDI3IHRpbWVzLiA8L3A+Cgo8aDM+PGZvbnQgZmFjZT0iVGltZXMgTmV3IFJvbWFuIj5QYXJ0IDUgLSBXaGF0IGFyZSB0aGV5IHRhbGtpbmcvZmVlbGluZyB1c2luZyBwZXJzb25hbCBwcm9ub3VuID8gPC9mb250PjwvaDM+Cgo8cD5JbiB0aGlzIHBhcnQsd2UgbWFpbmx5IG1ha2UgdHdvIHBsb3RzIHRvIGNvbXBhcmUuT25lIG9mIHRoZW0gaXMgc3RhY2tlZCBiYXIgcGxvdCxkZW1vbnN0cmF0aW5nIHRoZSBmb3VyIHByb3BvcnRpb25zIG9mIGZvdXIgcGVyc29uYWwgcHJvbm91bnMgZm9yIGVhY2ggc2VudGVuY2UgaW4gb25lIHNwZWVjaC5UaGUgc2Vjb25kIGlzIGFuIGFyZWEgcGxvdCxzaG93aW5nIGRpZmZlcmVudCBlbW90aW9ucyBmb3IgZWFjaCBzZW50ZW5jZSBpbiBvbmUgc3BlZWNoLjwvcD4KCjxoND48Zm9udCBmYWNlPSJUaW1lcyBOZXcgUm9tYW4iPkZpbmRpbmcgMTpmaXJzdCBzaW5ndWxhciBmb3JtIGFsd2F5cyBjb21lIHdpdGggdHJ1c3QgYW5kIGFudGljaXBhdGlvbi4gPC9mb250PjwvaDQ+CgorIEdlb3JnZSBXYXNoaW5ndG9uOiBUaGVyZSBhcmUgNCBzZW50ZW5jZXMgaW4gaGlzIHNwZWVjaGVzLHdpdGggMSwyIGFuZCA0IHVzaW5nIGhpZ2ggZnJlcXVlbmN5IG9mIGZpcnN0IHBlcnNvbiBzaW5ndWxhciBwcm9ub3VuLGFuZCB0aGUgZW1vdGlvbnMgb2YgdGhlc2Ugc2VudGVuY2VzIGFyZSBtYWlubHkgdHJ1c3QuCgoKYGBge3Isd2FybmluZz1GfQpzZW50ZW5fbWF0MjwtbWVsdChzZW50ZW5fbWF0KDIpKQpzZW5fZGF0PC1kYXRhLmZyYW1lKHNlbnRlbmNlLm51bWJlcj1zZW50ZW5fbWF0MiRWYXIxLHRpbWVzPXNlbnRlbl9tYXQyJHZhbHVlLHBlcnNvbmFsX3Byb25vdW49c2VudGVuX21hdDIkVmFyMiwyKQpzZW50aV9tYXQ8LXJvdW5kKGNvdW50X2VtbygyKVssYygxLDIsNCw1LDcsOCldLDIpCnJvd25hbWVzKHNlbnRpX21hdCk8LXNlcSgxLG5yb3coc2VudGlfbWF0KSkKc2VudGlfbWF0MjwtbWVsdChzZW50aV9tYXQpCnNlbnRpX2RhdDwtZGF0YS5mcmFtZShzZW50ZW5jZV9udW1iZXI9c2VudGlfbWF0MiRWYXIxLHNjb3JlPXNlbnRpX21hdDIkdmFsdWUsc2VudGltZW50PXNlbnRpX21hdDIkVmFyMikKCiNwYXIobWZyb3c9YygxLDIpKQphMTwtZ2dwbG90KHNlbl9kYXQsYWVzKHNlbnRlbmNlLm51bWJlcix0aW1lcyxmaWxsPXBlcnNvbmFsX3Byb25vdW4pKStnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb249InN0YWNrIikrZ2d0aXRsZSgiIikrZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPU5VTEwpKSsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJCbHVlcyIpKyB4bGFiKCJzZW50ZW5jZSBudW1iZXIiKQojYjE8LWdncGxvdChzZW50aV9kYXQsIGFlcyh4ID0gc2VudGVuY2VfbnVtYmVyLCB5ID0gc2NvcmUsIGZpbGwgPSBzZW50aW1lbnQpKSArCiMgIGdlb21fYXJlYSgpIAojICsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJSZEJ1IiwgYnJlYWtzID0gcmV2KGMoZmFjdG9yKHNlbnRpbWVudCkpKSkKI2IxPC1nZ3Bsb3Qoc2VudGlfZGF0LGFlcyh4ID0gc2VudGVuY2VfbnVtYmVyLCB5ID0gc2NvcmUsIGZpbGwgPSBzZW50aW1lbnQpKStnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb249InN0YWNrIikrZ2d0aXRsZSgiIikrZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPU5VTEwpKQojZ3JpZC5hcnJhbmdlKGExLGIxLG5yb3c9MikKYTEKYGBgCgoKYGBge3J9CmVBcmVhKHNlbnRpX21hdCkKI2ZpbmQgdG9waWNzCiN0ZXN0PC10b3BpY193YygyLDEpCiN0ZXN0PC10ZXN0Wzc6NjUsXQojZGF0PC1kYXRhLmZyYW1lKHdvcmQ9dGVzdFssIndvcmQiXSxmcmVxPXRlc3RbLCJuIl0pCiNlV29yZGNsb3VkKGRhdCwgbmFtZXZhciA9IH53b3JkLCBkYXRhdmFyID0gfmZyZXEsc2l6ZSA9IGMoNjAwLCA2MDApLHRpdGxlID0gIkdlb3JnZSBXYXNoaW5ndG9uICYgZmlzdCBwZXJzb24gc2luZ3VsYXIiLHJvdGF0aW9uUmFuZ2UgPSBjKC0xLCAxKSkKYGBgCltmb3IgdGhlIGFyZWEgcGxvdF0KCngtYXhpczpzZW50ZW5jZSBudW1iZXIKCnktYXhpczp0aGUgd2VpZ2h0IG9mIGEgY2VydGFpbiBraW5kIG9mIGVtb3Rpb24gYmVpbmcgZGV0ZWN0ZWQuCgorIFdpbGxpYW0gTWNLaW5sZXk6IFRoZSBzZW50ZW5jZXMgdXNpbmcgZmlyc3QgcGVyc29uIHNpbmd1bGFyIHByb25vdW4gZnJlcXVlbnRseSBhbHNvIGNvbnRhaW5zIHRydXN0IGVtb3Rpb24uCgoKYGBge3J9CnNlbnRlbl9tYXQyPC1tZWx0KHNlbnRlbl9tYXQoMjgpKQpzZW5fZGF0PC1kYXRhLmZyYW1lKHNlbnRlbmNlLm51bWJlcj1zZW50ZW5fbWF0MiRWYXIxLHRpbWVzPXNlbnRlbl9tYXQyJHZhbHVlLHBlcnNvbmFsX3Byb25vdW49c2VudGVuX21hdDIkVmFyMiwyKQpzZW50aV9tYXQ8LXJvdW5kKGNvdW50X2VtbygyOClbLGMoMSwyLDQsNSw3LDgpXSwyKQpyb3duYW1lcyhzZW50aV9tYXQpPC1zZXEoMSxucm93KHNlbnRpX21hdCkpCnNlbnRpX21hdDI8LW1lbHQoc2VudGlfbWF0KQpzZW50aV9kYXQ8LWRhdGEuZnJhbWUoc2VudGVuY2VfbnVtYmVyPXNlbnRpX21hdDIkVmFyMSxzY29yZT1zZW50aV9tYXQyJHZhbHVlLHNlbnRpbWVudD1zZW50aV9tYXQyJFZhcjIpCgojcGFyKG1mcm93PWMoMSwyKSkKYTE8LWdncGxvdChzZW5fZGF0LGFlcyhzZW50ZW5jZS5udW1iZXIsdGltZXMsZmlsbD1wZXJzb25hbF9wcm9ub3VuKSkrZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpK2dndGl0bGUoIiIpK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT1OVUxMKSkrIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiQmx1ZXMiKSsgeGxhYigic2VudGVuY2UgbnVtYmVyIikKI2IxPC1nZ3Bsb3Qoc2VudGlfZGF0LCBhZXMoeCA9IHNlbnRlbmNlX251bWJlciwgeSA9IHNjb3JlLCBmaWxsID0gc2VudGltZW50KSkgKwojICBnZW9tX2FyZWEoKSAKIyArIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiUmRCdSIsIGJyZWFrcyA9IHJldihjKGZhY3RvcihzZW50aW1lbnQpKSkpCiNiMTwtZ2dwbG90KHNlbnRpX2RhdCxhZXMoeCA9IHNlbnRlbmNlX251bWJlciwgeSA9IHNjb3JlLCBmaWxsID0gc2VudGltZW50KSkrZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpK2dndGl0bGUoIiIpK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT1OVUxMKSkKI2dyaWQuYXJyYW5nZShhMSxiMSxucm93PTIpCmExCmVBcmVhKHNlbnRpX21hdCkKCiNmaW5kX3NlbigyOCwxMzQpCiNmaW5kX3NlbigyOCwxMzUpCiNmaW5kX3NlbigyOCwxMzYpCiNmaW5kX3NlbigyOCwxMzcpCiN0ZXN0PC10b3BpY193YygyOCwxKVsxOjYwLF0KI3Rlc3Q8LXRlc3RbNjo2MCxdCiNkYXQ8LWRhdGEuZnJhbWUod29yZD10ZXN0Wywid29yZCJdLGZyZXE9dGVzdFssIm4iXSkKI2VXb3JkY2xvdWQoZGF0LCBuYW1ldmFyID0gfndvcmQsIGRhdGF2YXIgPSB+ZnJlcSxzaXplID0gYyg2MDAsIDYwMCksdGl0bGUgPSAiV2lsbGlhbU1jS2lubGV5ICYgZmlzdCBwZXJzb24gc2luZ3VsYXIiLHJvdGF0aW9uUmFuZ2UgPSBjKC0xLCAxKSkKYGBgCjxoND48Zm9udCBmYWNlPSJUaW1lcyBOZXcgUm9tYW4iPkZpbmRpbmcgMiA6Zmlyc3QgcGx1cmFsIGZvcm0gYWx3YXlzIGNvbnZleSBwb3NpdGl2ZSBlbW90aW9ucy48L2ZvbnQ+PC9oND4KCisgUmljaGFyZCBOaXhvbgoKYGBge3Isd2FybmluZz1GfQpzZW50ZW5fbWF0MjwtbWVsdChzZW50ZW5fbWF0KDQ1KSkKc2VuX2RhdDwtZGF0YS5mcmFtZShzZW50ZW5jZS5udW1iZXI9c2VudGVuX21hdDIkVmFyMSx0aW1lcz1zZW50ZW5fbWF0MiR2YWx1ZSxwZXJzb25hbF9wcm9ub3VuPXNlbnRlbl9tYXQyJFZhcjIpCgpwYXIobWZyb3c9Yyg0LDEpLCBtYXI9YygxLDAsMiwwKSwgYnR5PSJuIiwgeGF4dD0ibiIsIHlheHQ9Im4iLCBmb250Lm1haW49MSkKYTI8LWdncGxvdChzZW5fZGF0LGFlcyhzZW50ZW5jZS5udW1iZXIsdGltZXMsZmlsbD1wZXJzb25hbF9wcm9ub3VuKSkrZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpK2dndGl0bGUoIiIpK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT1OVUxMKSkrCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJCbHVlcyIpKyB4bGFiKCJzZW50ZW5jZSBudW1iZXIiKQoKc2VudGlfbWF0Mzwtcm91bmQoY291bnRfZW1vKDQ1KVssYygxLDIsNCw1LDcsOCldLDIpCnJvd25hbWVzKHNlbnRpX21hdDMpPC1zZXEoMSxucm93KHNlbnRpX21hdDMpKQpzZW50aV9tYXQ0PC1tZWx0KHNlbnRpX21hdDMpCnNlbnRpX2RhdDI8LWRhdGEuZnJhbWUoc2VudGVuY2VfbnVtYmVyPXNlbnRpX21hdDQkVmFyMSxzY29yZT1zZW50aV9tYXQ0JHZhbHVlLHNlbnRpbWVudD1zZW50aV9tYXQ0JFZhcjIpCiNiMjwtZ2dwbG90KHNlbnRpX2RhdDIsIGFlcyh4ID0gc2VudGVuY2VfbnVtYmVyLCB5ID0gc2NvcmUsIGZpbGwgPSBzZW50aW1lbnQpKSArCiMgIGdlb21fYXJlYSgpIAojYjI8LWdncGxvdChzZW50aV9kYXQyLGFlcyh4ID0gc2VudGVuY2VfbnVtYmVyLCB5ID0gc2NvcmUsIGZpbGwgPSBzZW50aW1lbnQpKStnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIscG9zaXRpb249InN0YWNrIikrZ2d0aXRsZSgiIikrZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPU5VTEwpKQphMgoKYGBgCgpgYGB7cn0KYXBwbHkoc2VudGlfbWF0MywyLG1lYW4pCmVBcmVhKHNlbnRpX21hdDMpCiN0ZXN0PC10b3BpY193Yyg0NSwyKVsxOjYwLF0KI2RhdDwtZGF0YS5mcmFtZSh3b3JkPXRlc3RbLCJ3b3JkIl0sZnJlcT10ZXN0WywibiJdKQojZVdvcmRjbG91ZChkYXQsIG5hbWV2YXIgPSB+d29yZCwgZGF0YXZhciA9IH5mcmVxKQpgYGAKCltmb3IgdGhlIGFyZWEgcGxvdF0KCngtYXhpczpzZW50ZW5jZSBudW1iZXIKCnktYXhpczp0aGUgd2VpZ2h0IG9mIGEgY2VydGFpbiBraW5kIG9mIGVtb3Rpb24gYmVpbmcgZGV0ZWN0ZWQuCgorIEJhcmFjayBPYmFtYQoKYGBge3J9CnNlbnRlbl9tYXQyPC1tZWx0KHNlbnRlbl9tYXQoNTcpKQpzZW5fZGF0PC1kYXRhLmZyYW1lKHNlbnRlbmNlLm51bWJlcj1zZW50ZW5fbWF0MiRWYXIxLHRpbWVzPXNlbnRlbl9tYXQyJHZhbHVlLHBlcnNvbmFsX3Byb25vdW49c2VudGVuX21hdDIkVmFyMiwyKQpzZW50aV9tYXQ8LXJvdW5kKGNvdW50X2Vtbyg1NylbLGMoMSwyLDQsNSw3LDgpXSwyKQpyb3duYW1lcyhzZW50aV9tYXQpPC1zZXEoMSxucm93KHNlbnRpX21hdCkpCnNlbnRpX21hdDI8LW1lbHQoc2VudGlfbWF0KQpzZW50aV9kYXQ8LWRhdGEuZnJhbWUoc2VudGVuY2VfbnVtYmVyPXNlbnRpX21hdDIkVmFyMSxzY29yZT1zZW50aV9tYXQyJHZhbHVlLHNlbnRpbWVudD1zZW50aV9tYXQyJFZhcjIpCgojcGFyKG1mcm93PWMoMSwyKSkKYTE8LWdncGxvdChzZW5fZGF0LGFlcyhzZW50ZW5jZS5udW1iZXIsdGltZXMsZmlsbD1wZXJzb25hbF9wcm9ub3VuKSkrZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpK2dndGl0bGUoIiIpK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT1OVUxMKSkrIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiQmx1ZXMiKSsgeGxhYigic2VudGVuY2UgbnVtYmVyIikKI2IxPC1nZ3Bsb3Qoc2VudGlfZGF0LCBhZXMoeCA9IHNlbnRlbmNlX251bWJlciwgeSA9IHNjb3JlLCBmaWxsID0gc2VudGltZW50KSkgKwojICBnZW9tX2FyZWEoKSAKIyArIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiUmRCdSIsIGJyZWFrcyA9IHJldihjKGZhY3RvcihzZW50aW1lbnQpKSkpCiNiMTwtZ2dwbG90KHNlbnRpX2RhdCxhZXMoeCA9IHNlbnRlbmNlX251bWJlciwgeSA9IHNjb3JlLCBmaWxsID0gc2VudGltZW50KSkrZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpK2dndGl0bGUoIiIpK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT1OVUxMKSkKI2dyaWQuYXJyYW5nZShhMSxiMSxucm93PTIpCmExCmVBcmVhKHNlbnRpX21hdCkKI2ZpbmRfc2VuKDI4LDEzNCkKI2ZpbmRfc2VuKDI4LDEzNSkKI2ZpbmRfc2VuKDI4LDEzNikKI2ZpbmRfc2VuKDI4LDEzNykKYXBwbHkoc2VudGlfbWF0LDIsbWVhbikKI3Rlc3Q8LXRvcGljX3djKDM1LDIpWzE6NjAsXQojZGF0PC1kYXRhLmZyYW1lKHdvcmQ9dGVzdFssIndvcmQiXSxmcmVxPXRlc3RbLCJuIl0pCiNlV29yZGNsb3VkKGRhdCwgbmFtZXZhciA9IH53b3JkLCBkYXRhdmFyID0gfmZyZXEpCmBgYAoKPGg0Pjxmb250IGZhY2U9IlRpbWVzIE5ldyBSb21hbiI+RmluZGluZyAzIDogQW5nZXIgb2Z0ZW4gYmVnaW4gd2l0aCB0aGlyZCBwZXJzb24gZm9ybS48L2ZvbnQ+PC9oND4KCisgVWx5c3NlcyBTLkdyYW50CgoKYGBge3J9CnNlbnRlbl9tYXQyPC1tZWx0KHNlbnRlbl9tYXQoMjEpKQpzZW5fZGF0PC1kYXRhLmZyYW1lKHNlbnRlbmNlLm51bWJlcj1zZW50ZW5fbWF0MiRWYXIxLHRpbWVzPXNlbnRlbl9tYXQyJHZhbHVlLHBlcnNvbmFsX3Byb25vdW49c2VudGVuX21hdDIkVmFyMikKYTM8LWdncGxvdChzZW5fZGF0LGFlcyhzZW50ZW5jZS5udW1iZXIsdGltZXMsZmlsbD1wZXJzb25hbF9wcm9ub3VuKSkrZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpK2dndGl0bGUoIiIpK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT1OVUxMKSkrIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiQmx1ZXMiKSsgeGxhYigic2VudGVuY2UgbnVtYmVyIikKc2VudGlfbWF0NTwtcm91bmQoY291bnRfZW1vKDIxKVssYygxLDIsNCw1LDcsOCldLDIpCnJvd25hbWVzKHNlbnRpX21hdDUpPC1zZXEoMSxucm93KHNlbnRpX21hdDUpKQpzZW50aV9tYXQ2PC1tZWx0KHNlbnRpX21hdDUpCnNlbnRpX2RhdDM8LWRhdGEuZnJhbWUoc2VudGVuY2VfbnVtYmVyPXNlbnRpX21hdDYkVmFyMSxzY29yZT1zZW50aV9tYXQ2JHZhbHVlLHNlbnRpbWVudD1zZW50aV9tYXQ2JFZhcjIpCmIzPC1nZ3Bsb3Qoc2VudGlfZGF0MyxhZXMoeCA9IHNlbnRlbmNlX251bWJlciwgeSA9IHNjb3JlLCBmaWxsID0gc2VudGltZW50KSkrZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPSJzdGFjayIpK2dndGl0bGUoIiIpK2d1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT1OVUxMKSkKI2IzPC1nZ3Bsb3Qoc2VudGlfZGF0MywgYWVzKHggPSBzZW50ZW5jZV9udW1iZXIsIHkgPSBzY29yZSwgZmlsbCA9IHNlbnRpbWVudCkpICsKIyAgZ2VvbV9hcmVhKCkgCmEzCmBgYAoKCmBgYHtyfQplQXJlYShzZW50aV9tYXQ1KQphcHBseShzZW50aV9tYXQ1LDIsbWVhbixuYS5ybT1UKQojdGVzdDwtdG9waWNfd2MoNTcsMilbMTo2MCxdCiNkYXQ8LWRhdGEuZnJhbWUod29yZD10ZXN0Wywid29yZCJdLGZyZXE9dGVzdFssIm4iXSkKI2VXb3JkY2xvdWQoZGF0LCBuYW1ldmFyID0gfndvcmQsIGRhdGF2YXIgPSB+ZnJlcSkKYGBgCltmb3IgdGhlIGFyZWEgcGxvdF0KCngtYXhpczpzZW50ZW5jZSBudW1iZXIKCnktYXhpczp0aGUgd2VpZ2h0IG9mIGEgY2VydGFpbiBraW5kIG9mIGVtb3Rpb24gYmVpbmcgZGV0ZWN0ZWQuCgoKKyBEd2lnaHQgRC5FaXNlbmhvd2VyCmBgYHtyfQpzZW50ZW5fbWF0MjwtbWVsdChzZW50ZW5fbWF0KDQzKSkKc2VuX2RhdDwtZGF0YS5mcmFtZShzZW50ZW5jZS5udW1iZXI9c2VudGVuX21hdDIkVmFyMSx0aW1lcz1zZW50ZW5fbWF0MiR2YWx1ZSxwZXJzb25hbF9wcm9ub3VuPXNlbnRlbl9tYXQyJFZhcjIpCmEzPC1nZ3Bsb3Qoc2VuX2RhdCxhZXMoc2VudGVuY2UubnVtYmVyLHRpbWVzLGZpbGw9cGVyc29uYWxfcHJvbm91bikpK2dlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj0ic3RhY2siKStnZ3RpdGxlKCIiKStndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9TlVMTCkpKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkJsdWVzIikrIHhsYWIoInNlbnRlbmNlIG51bWJlciIpCnNlbnRpX21hdDU8LXJvdW5kKGNvdW50X2Vtbyg0MylbLGMoMSwyLDQsNSw3LDgpXSwyKQpyb3duYW1lcyhzZW50aV9tYXQ1KTwtc2VxKDEsbnJvdyhzZW50aV9tYXQ1KSkKc2VudGlfbWF0NjwtbWVsdChzZW50aV9tYXQ1KQpzZW50aV9kYXQzPC1kYXRhLmZyYW1lKHNlbnRlbmNlX251bWJlcj1zZW50aV9tYXQ2JFZhcjEsc2NvcmU9c2VudGlfbWF0NiR2YWx1ZSxzZW50aW1lbnQ9c2VudGlfbWF0NiRWYXIyKQpiMzwtZ2dwbG90KHNlbnRpX2RhdDMsYWVzKHggPSBzZW50ZW5jZV9udW1iZXIsIHkgPSBzY29yZSwgZmlsbCA9IHNlbnRpbWVudCkpK2dlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj0ic3RhY2siKStnZ3RpdGxlKCIiKStndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9TlVMTCkpCiNiMzwtZ2dwbG90KHNlbnRpX2RhdDMsIGFlcyh4ID0gc2VudGVuY2VfbnVtYmVyLCB5ID0gc2NvcmUsIGZpbGwgPSBzZW50aW1lbnQpKSArCiMgIGdlb21fYXJlYSgpIAphMwplQXJlYShzZW50aV9tYXQ1KQphcHBseShzZW50aV9tYXQ1LDIsbWVhbixuYS5ybT1UKQojdGVzdDwtdG9waWNfd2MoNTcsMilbMTo2MCxdCiNkYXQ8LWRhdGEuZnJhbWUod29yZD10ZXN0Wywid29yZCJdLGZyZXE9dGVzdFssIm4iXSkKI2VXb3JkY2xvdWQoZGF0LCBuYW1ldmFyID0gfndvcmQsIGRhdGF2YXIgPSB+ZnJlcSkKYGBgCgoKPGgzPjxmb250IGZhY2U9IlRpbWVzIE5ldyBSb21hbiI+UGFydCA2IC0gTmV4dCBzdGVwPC9mb250PjwvaDM+CgorIDxoND48Zm9udCBmYWNlPSJUaW1lcyBOZXcgUm9tYW4iPkNvbGxlY3QgbW9yZSBkYXRhIGZvciBvdGhlciBmb3JtYWwgc3BlZWNoZXMgdG8gZ2FpbiBtb3JlIGNvbnZpbmNpbmcgYW5hbHlzaXMuPC9mb250PjwvaDQ+CisgPGg0Pjxmb250IGZhY2U9IlRpbWVzIE5ldyBSb21hbiI+U21vb3RoIHRoZSBlbW90aW9uIGZ1bmN0aW9uIHRvIG1ha2UgaXQgbW9yZSBjbGVhci48L2ZvbnQ+PC9oND4KCgo=